summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
authorChunseok Lee <chunseok.lee@samsung.com>2020-08-14 15:19:19 +0900
committerChunseok Lee <chunseok.lee@samsung.com>2020-08-14 15:19:19 +0900
commit042b262b3633b6c0f577aed6cb4b980ad0c1dcf3 (patch)
treee79fb9ffe65b21bdc5863306db2757ab187a3306 /compiler
parent05e0ec30a632339a8533082476f27bda31ccde16 (diff)
downloadnnfw-042b262b3633b6c0f577aed6cb4b980ad0c1dcf3.tar.gz
nnfw-042b262b3633b6c0f577aed6cb4b980ad0c1dcf3.tar.bz2
nnfw-042b262b3633b6c0f577aed6cb4b980ad0c1dcf3.zip
Imported Upstream version 1.8.0upstream/1.8.0submit/tizen/20200814.062151
Diffstat (limited to 'compiler')
-rw-r--r--compiler/.ahub/tcchecker-tca/config.yaml54
-rw-r--r--compiler/bcq-tools/CMakeLists.txt27
-rw-r--r--compiler/bcq-tools/README.md78
-rw-r--r--compiler/bcq-tools/generate_bcq_output_arrays90
-rw-r--r--compiler/bcq-tools/preserve_bcq_info116
-rw-r--r--compiler/circle-quantizer/CMakeLists.txt1
-rw-r--r--compiler/circle-quantizer/requires.cmake1
-rw-r--r--compiler/circle-quantizer/src/CircleQuantizer.cpp18
-rw-r--r--compiler/circle-tensordump/driver/Driver.cpp9
-rw-r--r--compiler/circle-tensordump/src/Dump.cpp48
-rw-r--r--compiler/circle-verify/src/Driver.cpp2
-rw-r--r--compiler/circle2circle-dredd-recipe-test/CMakeLists.txt93
-rw-r--r--compiler/circle2circle-dredd-recipe-test/requires.cmake4
-rw-r--r--compiler/circle2circle-dredd-recipe-test/test.lst3
-rwxr-xr-xcompiler/circle2circle-dredd-recipe-test/testall.sh13
-rw-r--r--compiler/circle2circle/CMakeLists.txt2
-rw-r--r--compiler/circle2circle/requires.cmake1
-rw-r--r--compiler/circle2circle/src/Circle2Circle.cpp14
-rw-r--r--compiler/circlechef/CMakeLists.txt4
-rw-r--r--compiler/circlechef/circle/src/RecipeChef.cpp2
-rw-r--r--compiler/circlechef/core/src/ModelChef.cpp1
-rw-r--r--compiler/circlechef/proto/circlechef.proto1
-rw-r--r--compiler/circlechef/tools/file/Driver.cpp2
-rw-r--r--compiler/circlechef/tools/reverse/Driver.cpp2
-rw-r--r--compiler/circledump/driver/Driver.cpp2
-rw-r--r--compiler/circledump/src/OpPrinter.cpp17
-rw-r--r--compiler/common-artifacts/CMakeLists.txt42
-rw-r--r--compiler/common-artifacts/exclude.lst35
-rw-r--r--compiler/common-artifacts/requires.cmake1
-rw-r--r--compiler/common-artifacts/src/TestDataGenerator.cpp32
-rw-r--r--compiler/hermes/src/hermes.test.cpp25
-rw-r--r--compiler/locomotiv/src/Node/BiasEncode.test.cpp14
-rw-r--r--compiler/locomotiv/src/Node/MatMul.test.cpp4
-rw-r--r--compiler/locop/src/FormattedGraph.test.cpp2
-rw-r--r--compiler/locop/src/FormattedTensorShape.test.cpp2
-rw-r--r--compiler/luci-interpreter/include/luci_interpreter/core/Tensor.h9
-rw-r--r--compiler/luci-interpreter/src/core/KernelParams.h5
-rw-r--r--compiler/luci-interpreter/src/kernels/Add.cpp5
-rw-r--r--compiler/luci-interpreter/src/kernels/Add.test.cpp27
-rw-r--r--compiler/luci-interpreter/src/kernels/CMakeLists.txt9
-rw-r--r--compiler/luci-interpreter/src/kernels/DepthToSpace.cpp90
-rw-r--r--compiler/luci-interpreter/src/kernels/DepthToSpace.h45
-rw-r--r--compiler/luci-interpreter/src/kernels/DepthToSpace.test.cpp60
-rw-r--r--compiler/luci-interpreter/src/kernels/L2Normalize.test.cpp9
-rw-r--r--compiler/luci-interpreter/src/kernels/LeakyRelu.test.cpp11
-rw-r--r--compiler/luci-interpreter/src/kernels/Logistic.test.cpp6
-rw-r--r--compiler/luci-interpreter/src/kernels/Reverse.cpp81
-rw-r--r--compiler/luci-interpreter/src/kernels/Reverse.h43
-rw-r--r--compiler/luci-interpreter/src/kernels/Reverse.test.cpp66
-rw-r--r--compiler/luci-interpreter/src/kernels/Slice.cpp149
-rw-r--r--compiler/luci-interpreter/src/kernels/Slice.h44
-rw-r--r--compiler/luci-interpreter/src/kernels/Slice.test.cpp64
-rw-r--r--compiler/luci-interpreter/src/kernels/TransposeConv.test.cpp23
-rw-r--r--compiler/luci-interpreter/src/loader/CMakeLists.txt7
-rw-r--r--compiler/luci-interpreter/src/loader/GraphLoader.cpp25
-rw-r--r--compiler/luci-interpreter/src/loader/GraphLoader.h18
-rw-r--r--compiler/luci-interpreter/src/loader/KernelBuilder.cpp113
-rw-r--r--compiler/luci-interpreter/src/loader/KernelBuilder.h17
-rw-r--r--compiler/luci-interpreter/src/loader/KernelBuilder.test.cpp743
-rw-r--r--compiler/luci-interpreter/src/loader/ModuleLoader.cpp7
-rw-r--r--compiler/luci-interpreter/src/loader/ModuleLoader.h5
-rw-r--r--compiler/luci-value-test/CMakeLists.txt2
-rwxr-xr-xcompiler/luci-value-test/evalverify.sh6
-rwxr-xr-xcompiler/luci-value-test/luci_eval_verifier.py78
-rw-r--r--compiler/luci-value-test/test.lst140
-rw-r--r--compiler/luci-value-test/tester/src/EvalTester.cpp47
-rw-r--r--compiler/luci/export/src/CircleOperationExporter.cpp90
-rw-r--r--compiler/luci/export/src/CircleTensorExporter.cpp5
-rw-r--r--compiler/luci/import/include/luci/Import/Nodes.h2
-rw-r--r--compiler/luci/import/include/luci/Import/Nodes/CircleNonMaxSuppressionV4.h35
-rw-r--r--compiler/luci/import/include/luci/Import/Nodes/CircleUnique.h35
-rw-r--r--compiler/luci/import/src/CircleReader.cpp2
-rw-r--r--compiler/luci/import/src/GraphBuilderRegistry.cpp4
-rw-r--r--compiler/luci/import/src/Importer.test.cpp7
-rw-r--r--compiler/luci/import/src/Nodes/CircleAbs.cpp2
-rw-r--r--compiler/luci/import/src/Nodes/CircleAdd.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleArgMax.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleArgMin.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleAveragePool2D.cpp2
-rw-r--r--compiler/luci/import/src/Nodes/CircleBCQFullyConnected.cpp10
-rw-r--r--compiler/luci/import/src/Nodes/CircleBCQGather.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleBatchMatMul.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleBatchToSpaceND.cpp12
-rw-r--r--compiler/luci/import/src/Nodes/CircleCast.cpp6
-rw-r--r--compiler/luci/import/src/Nodes/CircleCeil.cpp2
-rw-r--r--compiler/luci/import/src/Nodes/CircleConv2D.cpp6
-rw-r--r--compiler/luci/import/src/Nodes/CircleCos.cpp2
-rw-r--r--compiler/luci/import/src/Nodes/CircleDepthToSpace.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleDepthwiseConv2D.cpp6
-rw-r--r--compiler/luci/import/src/Nodes/CircleDiv.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleElu.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleEqual.cpp6
-rw-r--r--compiler/luci/import/src/Nodes/CircleExp.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleExpandDims.cpp6
-rw-r--r--compiler/luci/import/src/Nodes/CircleFill.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleFloor.cpp2
-rw-r--r--compiler/luci/import/src/Nodes/CircleFloorDiv.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleFloorMod.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleFullyConnected.cpp6
-rw-r--r--compiler/luci/import/src/Nodes/CircleGather.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleGatherNd.cpp6
-rw-r--r--compiler/luci/import/src/Nodes/CircleGreater.cpp6
-rw-r--r--compiler/luci/import/src/Nodes/CircleGreaterEqual.cpp6
-rw-r--r--compiler/luci/import/src/Nodes/CircleIf.cpp2
-rw-r--r--compiler/luci/import/src/Nodes/CircleInstanceNorm.cpp6
-rw-r--r--compiler/luci/import/src/Nodes/CircleL2Normalize.cpp2
-rw-r--r--compiler/luci/import/src/Nodes/CircleL2Pool2D.cpp2
-rw-r--r--compiler/luci/import/src/Nodes/CircleLeakyRelu.cpp2
-rw-r--r--compiler/luci/import/src/Nodes/CircleLess.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleLessEqual.cpp6
-rw-r--r--compiler/luci/import/src/Nodes/CircleLocalResponseNormalization.cpp2
-rw-r--r--compiler/luci/import/src/Nodes/CircleLog.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleLogSoftmax.cpp2
-rw-r--r--compiler/luci/import/src/Nodes/CircleLogicalAnd.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleLogicalNot.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleLogicalOr.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleLogistic.cpp18
-rw-r--r--compiler/luci/import/src/Nodes/CircleMatrixDiag.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleMatrixSetDiag.cpp6
-rw-r--r--compiler/luci/import/src/Nodes/CircleMaxPool2D.cpp2
-rw-r--r--compiler/luci/import/src/Nodes/CircleMaximum.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleMean.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleMinimum.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleMirrorPad.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleMul.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleNeg.cpp2
-rw-r--r--compiler/luci/import/src/Nodes/CircleNonMaxSuppressionV4.cpp123
-rw-r--r--compiler/luci/import/src/Nodes/CircleNotEqual.cpp6
-rw-r--r--compiler/luci/import/src/Nodes/CircleOneHot.cpp16
-rw-r--r--compiler/luci/import/src/Nodes/CirclePRelu.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CirclePad.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CirclePow.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleRange.cpp6
-rw-r--r--compiler/luci/import/src/Nodes/CircleRank.cpp2
-rw-r--r--compiler/luci/import/src/Nodes/CircleReduceAny.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleReduceMax.cpp6
-rw-r--r--compiler/luci/import/src/Nodes/CircleReduceMin.cpp6
-rw-r--r--compiler/luci/import/src/Nodes/CircleReduceProd.cpp6
-rw-r--r--compiler/luci/import/src/Nodes/CircleRelu.cpp2
-rw-r--r--compiler/luci/import/src/Nodes/CircleRelu6.cpp2
-rw-r--r--compiler/luci/import/src/Nodes/CircleReluN1To1.cpp2
-rw-r--r--compiler/luci/import/src/Nodes/CircleReshape.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleResizeBilinear.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleResizeNearestNeighbor.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleReverseSequence.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleReverseV2.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleRound.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleRsqrt.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleScatterNd.cpp12
-rw-r--r--compiler/luci/import/src/Nodes/CircleSegmentSum.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleSelect.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleSelectV2.cpp12
-rw-r--r--compiler/luci/import/src/Nodes/CircleShape.cpp2
-rw-r--r--compiler/luci/import/src/Nodes/CircleSin.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleSlice.cpp6
-rw-r--r--compiler/luci/import/src/Nodes/CircleSoftmax.cpp2
-rw-r--r--compiler/luci/import/src/Nodes/CircleSpaceToBatchND.cpp12
-rw-r--r--compiler/luci/import/src/Nodes/CircleSpaceToDepth.cpp2
-rw-r--r--compiler/luci/import/src/Nodes/CircleSparseToDense.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleSqrt.cpp2
-rw-r--r--compiler/luci/import/src/Nodes/CircleSquare.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleSquaredDifference.cpp10
-rw-r--r--compiler/luci/import/src/Nodes/CircleSqueeze.cpp2
-rw-r--r--compiler/luci/import/src/Nodes/CircleStridedSlice.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleSub.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleSum.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleTanh.cpp20
-rw-r--r--compiler/luci/import/src/Nodes/CircleTile.cpp10
-rw-r--r--compiler/luci/import/src/Nodes/CircleTopKV2.cpp2
-rw-r--r--compiler/luci/import/src/Nodes/CircleTranspose.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleTransposeConv.cpp24
-rw-r--r--compiler/luci/import/src/Nodes/CircleUnique.cpp89
-rw-r--r--compiler/luci/import/src/Nodes/CircleUnpack.cpp2
-rw-r--r--compiler/luci/import/src/Nodes/CircleWhere.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleZerosLike.cpp2
-rw-r--r--compiler/luci/lang/include/luci/IR/CircleNodes.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/CircleNodes.lst7
-rw-r--r--compiler/luci/lang/include/luci/IR/CircleQuantParam.h1
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleConst.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleNonMaxSuppressionV4.h53
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleNonMaxSuppressionV4Out.h51
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CirclePadV2.h49
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleUnique.h47
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleUniqueOut.h51
-rw-r--r--compiler/luci/lang/src/Module.test.cpp2
-rw-r--r--compiler/luci/lang/src/Nodes/CircleCustom.test.cpp7
-rw-r--r--compiler/luci/lang/src/Nodes/CircleIf.test.cpp4
-rw-r--r--compiler/luci/lang/src/Nodes/CircleNonMaxSuppressionV4.test.cpp96
-rw-r--r--compiler/luci/lang/src/Nodes/CircleNonMaxSuppressionV4Out.test.cpp32
-rw-r--r--compiler/luci/lang/src/Nodes/CirclePadV2.test.cpp86
-rw-r--r--compiler/luci/lang/src/Nodes/CircleUnique.test.cpp76
-rw-r--r--compiler/luci/lang/src/Nodes/CircleWhile.test.cpp4
-rw-r--r--compiler/luci/logex/src/FormattedGraph.cpp41
-rw-r--r--compiler/luci/pass/src/CircleOptimizer.cpp4
-rw-r--r--compiler/luci/pass/src/FuseBCQPass.cpp435
-rw-r--r--compiler/luci/pass/src/QuantizationUtils.cpp20
-rw-r--r--compiler/luci/pass/src/QuantizeWithMinMaxPass.cpp25
-rw-r--r--compiler/luci/service/src/CircleShapeInferenceRule.cpp59
-rw-r--r--compiler/luci/service/src/CircleTypeInferenceRule.cpp33
-rw-r--r--compiler/luci/tests/test.lst15
-rw-r--r--compiler/mio-tflite/CMakeLists.txt6
-rw-r--r--compiler/one-cmds/CMakeLists.txt3
-rw-r--r--compiler/one-cmds/how-to-prepare-virtualenv.txt4
-rw-r--r--compiler/one-cmds/how-to-use-one-commands.txt25
-rw-r--r--compiler/one-cmds/one-codegen25
-rw-r--r--compiler/one-cmds/one-import25
-rw-r--r--compiler/one-cmds/one-import-bcq150
-rw-r--r--compiler/one-cmds/one-import-tf30
-rw-r--r--compiler/one-cmds/one-import-tflite20
-rw-r--r--compiler/one-cmds/one-optimize20
-rw-r--r--compiler/one-cmds/one-pack32
-rw-r--r--compiler/one-cmds/one-prepare-venv16
-rw-r--r--compiler/one-cmds/one-quantize23
-rw-r--r--compiler/one-cmds/requires.cmake2
-rw-r--r--compiler/pota-quantization-value-test/CMakeLists.txt32
-rwxr-xr-xcompiler/pota-quantization-value-test/compare_tensors.py4
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/fake_quantization/ker.json44
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/quantization/bias.json14
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/quantization/ifm.json2
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/quantization/ker.json56
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/quantization/ofm.json2
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/record_minmax/ifm.json4
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/record_minmax/ofm.json4
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/fake_quantization/ker.json34
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/quantization/bias.json12
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/quantization/ifm.json2
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/quantization/ker.json40
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/quantization/ofm.json2
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/record_minmax/ifm.json4
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/record_minmax/ofm.json4
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/FullyConnected_003/layer/uint8/fake_quantization/weight.json76
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/FullyConnected_003/layer/uint8/quantization/bias.json9
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/FullyConnected_003/layer/uint8/quantization/in.json4
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/FullyConnected_003/layer/uint8/quantization/out.json4
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/FullyConnected_003/layer/uint8/quantization/weight.json80
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/FullyConnected_003/layer/uint8/record_minmax/in.json4
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/FullyConnected_003/layer/uint8/record_minmax/out.json4
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/TransposeConv_001/layer/uint8/fake_quantization/ker.json48
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/TransposeConv_001/layer/uint8/quantization/ifm.json4
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/TransposeConv_001/layer/uint8/quantization/ker.json52
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/TransposeConv_001/layer/uint8/quantization/ofm.json4
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/TransposeConv_001/layer/uint8/record_minmax/ifm.json4
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/TransposeConv_001/layer/uint8/record_minmax/ofm.json4
-rw-r--r--compiler/pota-quantization-value-test/test.lst2
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/Conv2D_004/layer/uint8/0.txt2
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/Conv2D_004/layer/uint8/1.txt1
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/Conv2D_004/layer/uint8/2.txt1
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/Conv2D_004/layer/uint8/3.txt1
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/Conv2D_004/layer/uint8/4.txt1
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/DepthwiseConv2D_002/layer/uint8/0.txt2
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/DepthwiseConv2D_002/layer/uint8/1.txt1
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/DepthwiseConv2D_002/layer/uint8/2.txt1
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/DepthwiseConv2D_002/layer/uint8/3.txt1
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/DepthwiseConv2D_002/layer/uint8/4.txt1
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/FullyConnected_003/layer/uint8/0.txt1
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/FullyConnected_003/layer/uint8/1.txt1
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/FullyConnected_003/layer/uint8/2.txt1
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/FullyConnected_003/layer/uint8/3.txt1
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/FullyConnected_003/layer/uint8/4.txt1
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/TransposeConv_001/layer/uint8/0.txt1
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/TransposeConv_001/layer/uint8/1.txt1
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/TransposeConv_001/layer/uint8/2.txt1
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/TransposeConv_001/layer/uint8/3.txt1
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/TransposeConv_001/layer/uint8/4.txt1
-rwxr-xr-xcompiler/pota-quantization-value-test/test_record_minmax.sh6
-rw-r--r--compiler/record-minmax/CMakeLists.txt5
-rw-r--r--compiler/record-minmax/driver/Driver.cpp16
-rw-r--r--compiler/record-minmax/requires.cmake1
-rw-r--r--compiler/record-minmax/src/HDF5Importer.cpp1
-rw-r--r--compiler/record-minmax/src/MinMaxObserver.cpp2
-rw-r--r--compiler/record-minmax/src/RecordMinMax.cpp2
-rw-r--r--compiler/record-minmax/tests/RecordFunction.test.cpp14
-rw-r--r--compiler/tf2circle-value-pbtxt-remote-test/CMakeLists.txt1
-rw-r--r--compiler/tf2circle-value-pbtxt-remote-test/README.md10
-rwxr-xr-xcompiler/tf2circle-value-pbtxt-remote-test/testall.sh13
-rw-r--r--compiler/tf2nnpackage-value-remote-test/CMakeLists.txt9
-rw-r--r--compiler/tf2nnpackage-value-remote-test/README.md4
-rwxr-xr-xcompiler/tf2nnpackage-value-remote-test/testall.sh13
-rw-r--r--compiler/tf2tfliteV2/README.md6
-rwxr-xr-xcompiler/tf2tfliteV2/tf2tfliteV2.py102
-rw-r--r--compiler/tfl-verify/CMakeLists.txt1
-rw-r--r--compiler/tfl-verify/requires.cmake1
-rw-r--r--compiler/tfl-verify/src/Driver.cpp19
-rw-r--r--compiler/tflchef/core/src/ModelChef.cpp1
-rw-r--r--compiler/tflchef/core/src/Op/NonMaxSuppressionV4.cpp30
-rw-r--r--compiler/tflchef/core/src/Op/NonMaxSuppressionV4.h52
-rw-r--r--compiler/tflchef/core/src/Op/PadV2.cpp28
-rw-r--r--compiler/tflchef/core/src/Op/PadV2.h46
-rw-r--r--compiler/tflchef/core/src/OpChef.def2
-rw-r--r--compiler/tflchef/core/src/OpChefs.h2
-rw-r--r--compiler/tflchef/proto/tflchef.proto13
-rw-r--r--compiler/tflchef/tflite/src/Op/NonMaxSuppressionV4.cpp56
-rw-r--r--compiler/tflchef/tflite/src/Op/NonMaxSuppressionV4.h39
-rw-r--r--compiler/tflchef/tflite/src/Op/PadV2.cpp42
-rw-r--r--compiler/tflchef/tflite/src/Op/PadV2.h39
-rw-r--r--compiler/tflchef/tflite/src/Op/TransposeConv.cpp4
-rw-r--r--compiler/tflchef/tflite/src/RecipeChef.cpp2
-rw-r--r--compiler/tflchef/tflite/src/TFliteOpChefs.h2
-rw-r--r--compiler/tflchef/tflite/src/TFliteOpRegistry.h2
-rw-r--r--compiler/tflchef/tools/file/Driver.cpp2
-rw-r--r--compiler/tflchef/tools/reverse/Driver.cpp2
-rw-r--r--compiler/tfldump/driver/Driver.cpp2
-rw-r--r--compiler/tfldump/src/OpPrinter.cpp1
-rw-r--r--compiler/tflite2circle/CMakeLists.txt1
-rw-r--r--compiler/tflite2circle/driver/Driver.cpp17
-rw-r--r--compiler/tflite2circle/requires.cmake1
-rw-r--r--compiler/tflite2circle/src/BuildBuiltinOptions.h2
-rw-r--r--compiler/tflite2circle/src/BuildBuiltinOptions/NonMaxSuppressionV4Options.cpp30
-rw-r--r--compiler/tflite2circle/src/BuildBuiltinOptions/NonMaxSuppressionV4Options.h32
-rw-r--r--compiler/tflite2circle/src/BuildBuiltinOptions/PadV2Options.cpp29
-rw-r--r--compiler/tflite2circle/src/BuildBuiltinOptions/PadV2Options.h31
-rw-r--r--compiler/tflite2circle/src/TFLBuiltinOptions.lst3
-rw-r--r--compiler/vconone/CMakeLists.txt31
-rw-r--r--compiler/vconone/README.md14
-rw-r--r--compiler/vconone/driver/driver.cpp36
-rw-r--r--compiler/vconone/include/vconone/vconone.h61
-rw-r--r--compiler/vconone/src/version.cpp63
-rw-r--r--compiler/vconone/src/version.test.cpp49
-rw-r--r--compiler/vconone/version_cfg.h.in22
319 files changed, 5770 insertions, 1066 deletions
diff --git a/compiler/.ahub/tcchecker-tca/config.yaml b/compiler/.ahub/tcchecker-tca/config.yaml
new file mode 100644
index 000000000..ef681de1a
--- /dev/null
+++ b/compiler/.ahub/tcchecker-tca/config.yaml
@@ -0,0 +1,54 @@
+version: 2
+test:
+ - name: NN Compiler
+ testCaseLanguage: CPP
+ testFW: GTEST
+ testCaseFolder:
+ - ./angkor
+ - ./arser
+ - ./circle2circle
+ - ./circle-quantizer
+ - ./cwrap
+ - ./foder
+ - ./hermes
+ - ./hermes-std
+ - ./loco
+ - ./locomotiv
+ - ./locop
+ - ./logo
+ - ./logo-core
+ - ./luci
+ - ./luci-interpreter
+ - ./luci-value-test
+ - ./mio-circle
+ - ./mio-tflite
+ - ./oops
+ - ./pepper-assert
+ - ./pepper-str
+ - ./pepper-strcast
+ - ./pp
+ - ./record-minmax
+ - ./safemain
+ - ./souschef
+ - ./stdex
+ - ./tflite2circle
+
+ testFile:
+ - extension: .test.cpp
+ any: true
+
+ testCase:
+ - condition:
+ - functionName:
+ starts:
+ - TEST
+
+ negativeTestCase:
+ - condition:
+ - testName:
+ ends:
+ - _NEG
+
+ positiveTestCase:
+ - condition:
+ - inverse: negativeTestCase
diff --git a/compiler/bcq-tools/CMakeLists.txt b/compiler/bcq-tools/CMakeLists.txt
new file mode 100644
index 000000000..fcf01de7d
--- /dev/null
+++ b/compiler/bcq-tools/CMakeLists.txt
@@ -0,0 +1,27 @@
+set(BCQ_TOOLS_FILES
+ generate_bcq_output_arrays
+ preserve_bcq_info
+)
+
+foreach(BCQ_TOOLS IN ITEMS ${BCQ_TOOLS_FILES})
+
+ set(BCQ_TOOLS_FILE ${BCQ_TOOLS})
+ set(BCQ_TOOLS_SRC "${CMAKE_CURRENT_SOURCE_DIR}/${BCQ_TOOLS_FILE}")
+ set(BCQ_TOOLS_BIN "${CMAKE_CURRENT_BINARY_DIR}/${BCQ_TOOLS_FILE}")
+ set(BCQ_TOOLS_TARGET "${BCQ_TOOLS}_target")
+
+ add_custom_command(OUTPUT ${BCQ_TOOLS_BIN}
+ COMMAND ${CMAKE_COMMAND} -E copy "${BCQ_TOOLS_SRC}" "${BCQ_TOOLS_BIN}"
+ DEPENDS ${BCQ_TOOLS_SRC}
+ COMMENT "Generate ${BCQ_TOOLS_BIN}"
+ )
+
+ add_custom_target(${BCQ_TOOLS_TARGET} ALL DEPENDS ${BCQ_TOOLS_BIN})
+
+ install(FILES ${BCQ_TOOLS_BIN}
+ PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE
+ GROUP_READ GROUP_EXECUTE
+ WORLD_READ WORLD_EXECUTE
+ DESTINATION bin)
+
+endforeach(BCQ_TOOLS)
diff --git a/compiler/bcq-tools/README.md b/compiler/bcq-tools/README.md
new file mode 100644
index 000000000..18b0f4826
--- /dev/null
+++ b/compiler/bcq-tools/README.md
@@ -0,0 +1,78 @@
+# BCQ Tools
+
+This directory includes some tools related with BCQ.
+
+## preserve_bcq_info
+
+### Purpose
+
+`preserve_bcq_info` is for preserving constant nodes which include BCQ information.
+When `.pb` file is converted to `.tflite` file by TFlite converter, constant nodes whose values are exactly same are removed and then linked to only one representative node.
+This makes us impossible to know what constant node should be linked to a node which we want to apply BCQ.
+One of the solutions is making all the same constant nodes different by inserting unique values and ignore the newly generated unique values when BCQ fusing is applied.
+`preserve_bcq_info` will generate and insert unique dummy values to the constant nodes whose values are same not to be removed by Tensorflow Lite converter.
+As a result, BCQ information will be preserved.
+
+### How to use
+
+```bash
+preserve_bcq_info \
+--input_path /path/to/original_model.pb \
+--output_path /path/to/preserved_model.pb
+```
+
+### How it works
+
+If we add unique dummy value at the end of each constant nodes, all the constant nodes would be different. Following is an example.
+
+```
+[Original Constant Nodes]
+const(value=[1, 2, 3], name='const1')
+const(value=[1, 2, 3], name='const2')
+const(value=[1, 2, 3], name='const3')
+
+[After BCQ information preserved]
+const(value=[1, 2, 3, -1], name='const1')
+const(value=[1, 2, 3, -2], name='const2')
+const(value=[1, 2, 3, -3], name='const3')
+```
+
+For dummy values, negative values are used instead of positive values.
+This is because positive valus may be confused with original constant node values.
+For your information, unique dummy value starts from -1 and moves to -2, -3, ..., -N, where N is the number of preserved constant nodes.
+
+### Caution
+
+- Newly generated dummy values should be ignored when the constant nodes are used.
+
+## generate_bcq_output_arrays
+
+### Purpose
+
+To apply BCQ, BCQ information nodes should be designated as model output so that they are alive even after TFLite conversion is finished.
+However, there are so many nodes to designate and sometimes we cannot copy and paste all of them because the string size is too big.
+`generate_bcq_output_arrays` is for generating output_arrays, which include BCQ information nodes.
+
+### How to use
+
+```bash
+generate_bcq_output_arrays \
+--input_path /path/to/original_model.pb \
+--output_path /path/to/output_arrays.txt
+```
+
+### How it works
+
+```
+[Original BCQ information nodes]
+const(value=[1, 2, 3, -1], name='const1')
+const(value=[1, 2, 3, -2], name='const2')
+const(value=[1, 2, 3, -3], name='const3')
+
+[Generated output_arrays]
+,const1,const2,const3
+```
+
+### Caution
+
+- Generated output_arrays will be start with comma.
diff --git a/compiler/bcq-tools/generate_bcq_output_arrays b/compiler/bcq-tools/generate_bcq_output_arrays
new file mode 100644
index 000000000..48e8a9373
--- /dev/null
+++ b/compiler/bcq-tools/generate_bcq_output_arrays
@@ -0,0 +1,90 @@
+#!/usr/bin/env python3
+
+import tensorflow as tf
+
+import argparse
+import sys
+
+
+def _get_parser():
+ """
+ Returns an ArgumentParser for generating output_arrays.
+ """
+ parser = argparse.ArgumentParser(
+ description=("Command line tool to generated output_arrays of BCQ nodes"))
+
+ # Input and output path.
+ parser.add_argument(
+ "-i",
+ "--input_path",
+ type=str,
+ help="Full filepath of the input file.",
+ required=True)
+ parser.add_argument(
+ "-o",
+ "--output_path",
+ type=str,
+ help="Full filepath of the output file.",
+ required=True)
+
+ return parser
+
+
+def load_graph(frozen_graph_filename):
+ """
+ Load graph from frozen pb file
+ """
+ with tf.compat.v1.gfile.GFile(frozen_graph_filename, "rb") as f:
+ graph_def = tf.compat.v1.GraphDef()
+ graph_def.ParseFromString(f.read())
+ with tf.Graph().as_default() as graph:
+ tf.import_graph_def(graph_def, name='')
+ return graph
+
+
+def dtype2str(dtype):
+ if dtype == "int32":
+ return "TF_INT32"
+ elif dtype == "int64":
+ return "TF_INT64"
+ elif dtype == "float32":
+ return "TF_FLOAT"
+ elif dtype == "bool":
+ return "TF_BOOL"
+ else:
+ raise Exception("Not supported dtype")
+
+
+def print_output_arrays(flags):
+ graph_model = load_graph(flags.input_path)
+ graph_model_def = graph_model.as_graph_def()
+ ops = graph_model.get_operations()
+
+ output_names = [op.outputs[0].name for op in ops
+ if op.type == "Const" and "bcqinfo_" in op.outputs[0].name]
+
+ output_arrays = ""
+ for output_name in output_names:
+ output_arrays += ","
+
+ colon_index = output_name.find(":")
+ if colon_index == -1:
+ output_arrays += output_name
+ else:
+ output_arrays += output_name[:colon_index]
+
+ f = open(flags.output_path, 'w')
+ f.write(output_arrays)
+ f.close()
+
+
+def main():
+ # Parse argument.
+ parser = _get_parser()
+ flags = parser.parse_known_args(args=sys.argv[1:])
+
+ print_output_arrays(flags[0])
+
+
+if __name__ == "__main__":
+ main()
diff --git a/compiler/bcq-tools/preserve_bcq_info b/compiler/bcq-tools/preserve_bcq_info
new file mode 100644
index 000000000..2ede8d4d0
--- /dev/null
+++ b/compiler/bcq-tools/preserve_bcq_info
@@ -0,0 +1,116 @@
+#!/usr/bin/env python3
+
+import tensorflow as tf
+import numpy as np
+
+import argparse
+import sys
+
+
+def _get_parser():
+ """
+ Returns an ArgumentParser for preserving BCQ information.
+ """
+ parser = argparse.ArgumentParser(
+ description=("Command line tool to preserve BCQ information"))
+
+ # Input and output path.
+ parser.add_argument(
+ "-i",
+ "--input_path",
+ type=str,
+ help="Full filepath of the input file.",
+ required=True)
+ parser.add_argument(
+ "-o",
+ "--output_path",
+ type=str,
+ help="Full filepath of the output file.",
+ required=True)
+
+ return parser
+
+
+def load_graph(frozen_graph_filename):
+ """
+ Load graph from frozen pb file
+ """
+ with tf.compat.v1.gfile.GFile(frozen_graph_filename, "rb") as f:
+ graph_def = tf.compat.v1.GraphDef()
+ graph_def.ParseFromString(f.read())
+ with tf.Graph().as_default() as graph:
+ tf.import_graph_def(graph_def, name='')
+ return graph
+
+
+def preserve_bcq_info(flags):
+ """
+ Generate unique dummy value from -1 to -N.
+
+ We use negative values to preserve BCQ information because
+ positive values may cause some confusion with real BCQ information values.
+ """
+
+ class UniqueValueGen:
+ def __init__(self):
+ self.unique_value = -1
+
+ def gen(self):
+ val = self.unique_value
+ self.unique_value = val - 1
+ return val
+
+ unique_value = UniqueValueGen()
+
+ original_graph_model = load_graph(flags.input_path)
+ original_graph_model_def = original_graph_model.as_graph_def()
+
+ new_graph = tf.compat.v1.GraphDef()
+ substitution_dict = {}
+
+ DT_INT32 = None # Just for copying DT_INT32 attribute value
+
+ for node in original_graph_model_def.node:
+ if node.op == "Const":
+ # Because bcqinfo_do_w_x is BOOL type, we cannot add dummy value at the end.
+ # Therefore we should convert the type to INT32 type.
+ if "/bcqinfo_do_w_x" in node.name:
+ original_tensor = tf.make_ndarray(node.attr["value"].tensor)
+ substitution_dict[node.name] = tf.make_tensor_proto(
+ [int(original_tensor[0]), unique_value.gen()], tf.int32)
+
+ preserved_bcqinfo_list = ["/bcqinfo_number_of_clusters", "/bcqinfo_size_of_clusters",
+ "/bcqinfo_qbits_of_clusters"]
+
+ if any(name in node.name for name in preserved_bcqinfo_list):
+ original_tensor = tf.make_ndarray(
+ node.attr["value"].tensor) # variable name change
+ substitution_dict[node.name] = tf.make_tensor_proto(
+ np.append(original_tensor, unique_value.gen()), tf.int32)
+ DT_INT32 = node.attr["dtype"]
+
+ for node in original_graph_model_def.node:
+ if node.name in substitution_dict:
+ new_node = new_graph.node.add()
+ new_node.op = "Const"
+ new_node.name = node.name
+ new_node.attr["dtype"].CopyFrom(DT_INT32)
+ new_node.attr["value"].tensor.CopyFrom(substitution_dict[node.name])
+ else:
+ new_node = new_graph.node.add()
+ new_node.CopyFrom(node)
+
+ tf.io.write_graph(new_graph, '.', flags.output_path, False)
+
+
+def main():
+ # Parse argument.
+ parser = _get_parser()
+ flags = parser.parse_known_args(args=sys.argv[1:])
+
+ # Generate a new pb file, which BCQ information is preserved.
+ preserve_bcq_info(flags[0])
+
+
+if __name__ == "__main__":
+ main()
diff --git a/compiler/circle-quantizer/CMakeLists.txt b/compiler/circle-quantizer/CMakeLists.txt
index 1335057eb..009bfabea 100644
--- a/compiler/circle-quantizer/CMakeLists.txt
+++ b/compiler/circle-quantizer/CMakeLists.txt
@@ -13,5 +13,6 @@ target_link_libraries(circle-quantizer luci_service)
target_link_libraries(circle-quantizer luci_pass)
target_link_libraries(circle-quantizer luci_export)
target_link_libraries(circle-quantizer arser)
+target_link_libraries(circle-quantizer vconone)
install(TARGETS circle-quantizer DESTINATION bin)
diff --git a/compiler/circle-quantizer/requires.cmake b/compiler/circle-quantizer/requires.cmake
index 2293e53f8..c21e28e8d 100644
--- a/compiler/circle-quantizer/requires.cmake
+++ b/compiler/circle-quantizer/requires.cmake
@@ -5,3 +5,4 @@ require("safemain")
require("luci")
require("oops")
require("arser")
+require("vconone")
diff --git a/compiler/circle-quantizer/src/CircleQuantizer.cpp b/compiler/circle-quantizer/src/CircleQuantizer.cpp
index b56b547a9..8d3a80c91 100644
--- a/compiler/circle-quantizer/src/CircleQuantizer.cpp
+++ b/compiler/circle-quantizer/src/CircleQuantizer.cpp
@@ -25,6 +25,7 @@
#include <oops/InternalExn.h>
#include <arser/arser.h>
+#include <vconone/vconone.h>
#include <functional>
#include <iostream>
@@ -36,6 +37,12 @@ using OptionHook = std::function<int(const char **)>;
using Algorithms = luci::CircleOptimizer::Options::Algorithm;
using AlgorithmParameters = luci::CircleOptimizer::Options::AlgorithmParameters;
+void print_version(void)
+{
+ std::cout << "circle-quantizer version " << vconone::get_string() << std::endl;
+ std::cout << vconone::get_copyright() << std::endl;
+}
+
int entry(int argc, char **argv)
{
// Simple argument parser (based on map)
@@ -49,13 +56,20 @@ int entry(int argc, char **argv)
arser::Arser arser("circle-quantizer provides circle model quantization");
+ arser.add_argument("--version")
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("Show version information and exit")
+ .exit_with(print_version);
+
arser.add_argument(qdqw)
.nargs(3)
.type(arser::DataType::STR_VEC)
.required(false)
.help("Quantize-dequantize weight values required action before quantization. "
"Three arguments required: input_dtype(float32) "
- "output_dtype(uint8) granularity(layer)");
+ "output_dtype(uint8) granularity(layer, channel)");
arser.add_argument(qwmm)
.nargs(3)
@@ -63,7 +77,7 @@ int entry(int argc, char **argv)
.required(false)
.help("Quantize with min/max values. "
"Three arguments required: input_dtype(float32) "
- "output_dtype(uint8) granularity(layer)");
+ "output_dtype(uint8) granularity(layer, channel)");
arser.add_argument("input").nargs(1).type(arser::DataType::STR).help("Input circle model");
arser.add_argument("output").nargs(1).type(arser::DataType::STR).help("Output circle model");
diff --git a/compiler/circle-tensordump/driver/Driver.cpp b/compiler/circle-tensordump/driver/Driver.cpp
index a55cd4574..5bab9f59e 100644
--- a/compiler/circle-tensordump/driver/Driver.cpp
+++ b/compiler/circle-tensordump/driver/Driver.cpp
@@ -46,7 +46,14 @@ int entry(int argc, char **argv)
{
std::cout << err.what() << std::endl;
std::cout << arser;
- return 0;
+ return 255;
+ }
+
+ if (arser["--tensors_to_hdf5"] == arser["--tensors"])
+ {
+ std::cout << "[Error] You must specify one option for how to print." << std::endl;
+ std::cout << arser;
+ return 255;
}
std::unique_ptr<circletensordump::DumpInterface> dump;
diff --git a/compiler/circle-tensordump/src/Dump.cpp b/compiler/circle-tensordump/src/Dump.cpp
index dfa78f031..a8d32564f 100644
--- a/compiler/circle-tensordump/src/Dump.cpp
+++ b/compiler/circle-tensordump/src/Dump.cpp
@@ -136,6 +136,7 @@ void DumpTensors::run(std::ostream &os, const circle::Model *model, const std::s
auto max = quant_param->max();
auto scale = quant_param->scale();
auto zero_point = quant_param->zero_point();
+ auto quantized_dimension = quant_param->quantized_dimension();
os << " " + print_format2 + "   ├── min : ";
::print_comma_sepearted(os, min);
@@ -146,9 +147,11 @@ void DumpTensors::run(std::ostream &os, const circle::Model *model, const std::s
os << " " + print_format2 + "   ├── scale : ";
::print_comma_sepearted(os, scale);
os << std::endl;
- os << " " + print_format2 + "   └── zero_point : ";
+ os << " " + print_format2 + "   ├── zero_point : ";
::print_comma_sepearted(os, zero_point);
os << std::endl;
+ os << " " + print_format2 + "   └── quantized_dimension : " << quantized_dimension;
+ os << std::endl;
}
// buffer
@@ -229,7 +232,7 @@ std::vector<hsize_t> hdf5_dims_cast(const flatbuffers::Vector<T> *data,
}
/**
- * This function writes data to given hdf5 file like below.
+ * This function writes vector data to given hdf5 file like below.
*
* GROUP "group_name"
* ã„´DATATYPE "type"
@@ -238,9 +241,9 @@ std::vector<hsize_t> hdf5_dims_cast(const flatbuffers::Vector<T> *data,
* ã„´DATA "data"
*/
template <typename T>
-void write_data_to_hdf5(H5::H5File &file, std::string &group_name, std::string dataset_name,
- const H5::PredType &type, const flatbuffers::Vector<T> *data,
- std::vector<hsize_t> dims)
+void write_vector_data_to_hdf5(H5::H5File &file, std::string &group_name, std::string dataset_name,
+ const H5::PredType &type, const flatbuffers::Vector<T> *data,
+ std::vector<hsize_t> dims)
{
if (data == nullptr)
return;
@@ -250,6 +253,17 @@ void write_data_to_hdf5(H5::H5File &file, std::string &group_name, std::string d
dataset->write(data->data(), type);
}
+/// @brief This function writes scalar data to given hdf5 file
+template <typename T>
+void write_scalar_data_to_hdf5(H5::H5File &file, std::string &group_name, std::string dataset_name,
+ const H5::PredType &type, T data)
+{
+ auto dataspace = std::make_unique<H5::DataSpace>(H5S_SCALAR);
+ auto dataset = std::make_unique<H5::DataSet>(
+ file.createDataSet(group_name + "/" + dataset_name, type, *dataspace));
+ dataset->write(&data, type);
+}
+
} // namespace
namespace circletensordump
@@ -297,8 +311,9 @@ void DumpTensorsToHdf5::run(std::ostream &os, const circle::Model *model,
auto buff_data_ptr = reader.buffers()->Get(buff_idx)->data();
if (buff_data_ptr)
{
- ::write_data_to_hdf5(file, group_name, "weights", ::hdf5_dtype_cast(tensor->type()),
- buff_data_ptr, ::hdf5_dims_cast(buff_data_ptr, tensor->shape()));
+ ::write_vector_data_to_hdf5(file, group_name, "weights", ::hdf5_dtype_cast(tensor->type()),
+ buff_data_ptr,
+ ::hdf5_dims_cast(buff_data_ptr, tensor->shape()));
}
// write quantization parameters
@@ -306,17 +321,20 @@ void DumpTensorsToHdf5::run(std::ostream &os, const circle::Model *model,
if (quant_param)
{
auto min = quant_param->min();
- ::write_data_to_hdf5(file, group_name, "min", H5::PredType::NATIVE_FLOAT, min,
- ::hdf5_dims_cast(min));
+ ::write_vector_data_to_hdf5(file, group_name, "min", H5::PredType::NATIVE_FLOAT, min,
+ ::hdf5_dims_cast(min));
auto max = quant_param->max();
- ::write_data_to_hdf5(file, group_name, "max", H5::PredType::NATIVE_FLOAT, max,
- ::hdf5_dims_cast(max));
+ ::write_vector_data_to_hdf5(file, group_name, "max", H5::PredType::NATIVE_FLOAT, max,
+ ::hdf5_dims_cast(max));
auto scale = quant_param->scale();
- ::write_data_to_hdf5(file, group_name, "scale", H5::PredType::NATIVE_FLOAT, scale,
- ::hdf5_dims_cast(scale));
+ ::write_vector_data_to_hdf5(file, group_name, "scale", H5::PredType::NATIVE_FLOAT, scale,
+ ::hdf5_dims_cast(scale));
auto zero_point = quant_param->zero_point();
- ::write_data_to_hdf5(file, group_name, "zero_point", H5::PredType::NATIVE_INT64, zero_point,
- ::hdf5_dims_cast(zero_point));
+ ::write_vector_data_to_hdf5(file, group_name, "zero_point", H5::PredType::NATIVE_INT64,
+ zero_point, ::hdf5_dims_cast(zero_point));
+ auto quantized_dimension = quant_param->quantized_dimension();
+ ::write_scalar_data_to_hdf5(file, group_name, "quantized_dimension",
+ H5::PredType::NATIVE_INT32, quantized_dimension);
}
}
}
diff --git a/compiler/circle-verify/src/Driver.cpp b/compiler/circle-verify/src/Driver.cpp
index 1af31d986..7a44c65b9 100644
--- a/compiler/circle-verify/src/Driver.cpp
+++ b/compiler/circle-verify/src/Driver.cpp
@@ -35,7 +35,7 @@ int entry(int argc, char **argv)
{
std::cout << err.what() << std::endl;
std::cout << arser;
- return 0;
+ return 255;
}
auto verifier = std::make_unique<VerifyFlatbuffers>();
diff --git a/compiler/circle2circle-dredd-recipe-test/CMakeLists.txt b/compiler/circle2circle-dredd-recipe-test/CMakeLists.txt
index 6663cb938..4bcaae347 100644
--- a/compiler/circle2circle-dredd-recipe-test/CMakeLists.txt
+++ b/compiler/circle2circle-dredd-recipe-test/CMakeLists.txt
@@ -1,25 +1,12 @@
nnas_include(TargetRequire)
unset(REQUIRED_TARGETS)
-list(APPEND REQUIRED_TARGETS circlechef)
list(APPEND REQUIRED_TARGETS circle-inspect)
list(APPEND REQUIRED_TARGETS circle-verify)
list(APPEND REQUIRED_TARGETS circle2circle)
list(APPEND REQUIRED_TARGETS dredd_rule_lib)
-list(APPEND REQUIRED_TARGETS tflchef)
-list(APPEND REQUIRED_TARGETS tflite2circle)
TargetRequire_Return(${REQUIRED_TARGETS})
-nncc_find_resource(TensorFlowLiteRecipes)
-nncc_find_resource(CircleRecipes)
-
-set(TFLITE_RECIPE_REPO "${TensorFlowLiteRecipes_DIR}")
-set(CIRCLE_RECIPE_REPO "${CircleRecipes_DIR}")
-unset(RECIPE_REPO)
-
-set(TEST_RECIPE_FILENAME "test.recipe")
-set(TEST_RULE_FILENAME "test.rule")
-
unset(TEST_DEPS)
unset(TEST_NAMES)
@@ -27,21 +14,9 @@ set(options "")
set(oneValueArgs "")
set(multiValueArgs PASS)
-macro(Add RECIPE)
- if(NOT EXISTS "${TFLITE_RECIPE_REPO}/${RECIPE}/test.recipe")
- if(NOT EXISTS "${CIRCLE_RECIPE_REPO}/${RECIPE}/test.recipe")
- message(FATAL_ERROR "Missing recipe of '${RECIPE}' test")
- else()
- set(RECIPE_REPO ${CIRCLE_RECIPE_REPO})
- endif()
- else()
- set(RECIPE_REPO ${TFLITE_RECIPE_REPO})
- endif()
-
- if(NOT EXISTS "${RECIPE_REPO}/${RECIPE}/test.rule")
- message(FATAL_ERROR "Missing rule of '${RECIPE}' test")
- endif()
+get_target_property(ARTIFACTS_BIN_PATH testDataGenerator BINARY_DIR)
+macro(Add RECIPE)
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
unset(OPT_OPTIONS)
foreach(src ${ARG_PASS})
@@ -49,71 +24,20 @@ macro(Add RECIPE)
list(APPEND OPT_OPTIONS "--${src}")
endforeach(src ${ARG_PASS})
- set(RECIPE_FILE "${RECIPE}.recipe")
- set(RECIPE_SOURCE_PATH "${RECIPE_REPO}/${RECIPE}/${TEST_RECIPE_FILENAME}")
- set(RECIPE_BINARY_PATH "${CMAKE_CURRENT_BINARY_DIR}/${RECIPE_FILE}")
-
- set(RULE_FILE "${RECIPE}.rule")
- set(RULE_SOURCE_PATH "${RECIPE_REPO}/${RECIPE}/${TEST_RULE_FILENAME}")
- set(RULE_BINARY_PATH "${CMAKE_CURRENT_BINARY_DIR}/${RULE_FILE}")
-
- set(TFLITE_FILE "${RECIPE}.tflite")
- set(TFLITE_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}/${TFLITE_FILE}")
-
set(CIRCLE_FILE "${RECIPE}.circle")
- set(CIRCLE_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}/${CIRCLE_FILE}")
+ set(CIRCLE_PATH "${ARTIFACTS_BIN_PATH}/${CIRCLE_FILE}")
set(OPT_CIRCLE_FILE "${RECIPE}.opt.circle")
set(OPT_CIRCLE_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}/${OPT_CIRCLE_FILE}")
- # Copy .recipe
- add_custom_command(OUTPUT ${RECIPE_BINARY_PATH}
- COMMAND ${CMAKE_COMMAND} -E copy "${RECIPE_SOURCE_PATH}" "${RECIPE_BINARY_PATH}"
- DEPENDS ${RECIPE_SOURCE_PATH}
- COMMENT "Generate ${RECIPE_FILE}"
- )
-
- # Copy .rule
- add_custom_command(OUTPUT ${RULE_BINARY_PATH}
- COMMAND ${CMAKE_COMMAND} -E copy "${RULE_SOURCE_PATH}" "${RULE_BINARY_PATH}"
- DEPENDS ${RULE_SOURCE_PATH}
- COMMENT "Generate ${RULE_FILE}"
- )
-
- if(${RECIPE_REPO} STREQUAL ${TFLITE_RECIPE_REPO})
- # Generate .tflite
- add_custom_command(OUTPUT ${TFLITE_OUTPUT_PATH}
- COMMAND $<TARGET_FILE:tflchef-file> ${RECIPE_BINARY_PATH} ${TFLITE_OUTPUT_PATH}
- DEPENDS $<TARGET_FILE:tflchef-file> ${RECIPE_BINARY_PATH}
- COMMENT "Generate ${TFLITE_FILE}"
- )
-
- # Generate .circle
- add_custom_command(OUTPUT ${CIRCLE_OUTPUT_PATH}
- COMMAND $<TARGET_FILE:tflite2circle> ${TFLITE_OUTPUT_PATH} ${CIRCLE_OUTPUT_PATH}
- DEPENDS $<TARGET_FILE:tflite2circle> ${TFLITE_OUTPUT_PATH}
- COMMENT "Generate ${CIRCLE_FILE}"
- )
-
- list(APPEND TEST_DEPS ${TFLITE_OUTPUT_PATH})
- else()
- # Generate .circle
- add_custom_command(OUTPUT ${CIRCLE_OUTPUT_PATH}
- COMMAND $<TARGET_FILE:circlechef-file> ${RECIPE_BINARY_PATH} ${CIRCLE_OUTPUT_PATH}
- DEPENDS $<TARGET_FILE:circlechef-file> ${RECIPE_BINARY_PATH}
- COMMENT "Generate ${CIRCLE_FILE}"
- )
- endif()
-
# Generate optimized .circle
add_custom_command(OUTPUT ${OPT_CIRCLE_OUTPUT_PATH}
- COMMAND $<TARGET_FILE:circle2circle> ${OPT_OPTIONS} ${CIRCLE_OUTPUT_PATH} ${OPT_CIRCLE_OUTPUT_PATH}
- DEPENDS $<TARGET_FILE:circle2circle> ${CIRCLE_OUTPUT_PATH}
+ COMMAND $<TARGET_FILE:circle2circle> ${OPT_OPTIONS} ${CIRCLE_PATH} ${OPT_CIRCLE_OUTPUT_PATH}
+ DEPENDS $<TARGET_FILE:circle2circle> ${CIRCLE_PATH}
COMMENT "Generate ${OPT_CIRCLE_FILE}"
)
- list(APPEND TEST_DEPS ${RECIPE_BINARY_PATH} ${RULE_BINARY_PATH}
- ${CIRCLE_OUTPUT_PATH} ${OPT_CIRCLE_OUTPUT_PATH})
+ list(APPEND TEST_DEPS ${OPT_CIRCLE_OUTPUT_PATH})
list(APPEND TEST_NAMES ${RECIPE})
endmacro(Add)
@@ -174,12 +98,15 @@ list(APPEND TEST_DEPS "${RULE_LIB_BINARY_PATH}")
# Generate dependencies
add_custom_target(circle2circle_dredd_recipe_test ALL DEPENDS ${TEST_DEPS})
+add_dependencies(circle2circle_dredd_recipe_test common_artifacts_deps)
+
+get_target_property(ARTIFACTS_BIN_PATH testDataGenerator BINARY_DIR)
# Run tests
add_test(
NAME circle2circle_dredd_recipe_test
COMMAND "${TEST_RUNNER}"
"${TEST_CONFIG}"
- "${CMAKE_CURRENT_BINARY_DIR}"
+ "${ARTIFACTS_BIN_PATH}"
${TEST_NAMES}
)
diff --git a/compiler/circle2circle-dredd-recipe-test/requires.cmake b/compiler/circle2circle-dredd-recipe-test/requires.cmake
index e4a5b71a7..70e7c5295 100644
--- a/compiler/circle2circle-dredd-recipe-test/requires.cmake
+++ b/compiler/circle2circle-dredd-recipe-test/requires.cmake
@@ -1,7 +1,5 @@
-require("circlechef")
require("circle2circle")
require("circle-inspect")
require("circle-verify")
+require("common-artifacts")
require("dredd-rule-lib")
-require("tflchef")
-require("tflite2circle")
diff --git a/compiler/circle2circle-dredd-recipe-test/test.lst b/compiler/circle2circle-dredd-recipe-test/test.lst
index 202f66938..6328a64db 100644
--- a/compiler/circle2circle-dredd-recipe-test/test.lst
+++ b/compiler/circle2circle-dredd-recipe-test/test.lst
@@ -11,9 +11,10 @@
## TFLITE RECIPE
Add(Net_InstanceNorm_001 PASS fuse_instnorm)
-# Add(Net_InstanceNorm_002 PASS fuse_instnorm)
+Add(Net_InstanceNorm_002 PASS fuse_instnorm)
Add(BatchMatMulV2_000 PASS resolve_customop_batchmatmul)
Add(MatMul_000 PASS resolve_customop_matmul)
+Add(DepthwiseConv2D_003 PASS)
## CIRCLE RECIPE
diff --git a/compiler/circle2circle-dredd-recipe-test/testall.sh b/compiler/circle2circle-dredd-recipe-test/testall.sh
index 33a2036bb..2899587ba 100755
--- a/compiler/circle2circle-dredd-recipe-test/testall.sh
+++ b/compiler/circle2circle-dredd-recipe-test/testall.sh
@@ -13,21 +13,22 @@ if [[ $# -lt 2 ]]; then
exit 255
fi
+WORKDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
CONFIG_PATH="$1"; shift
-WORKDIR="$1"; shift
+RESOURCE_DIR="$1"; shift
source "${CONFIG_PATH}"
echo "-- Found circle-inspect: ${CIRCLE_INSPECT_PATH}"
echo "-- Found circle-verify: ${CIRCLE_VERIFY_PATH}"
echo "-- Found circle2circle: ${CIRCLE2CIRCLE_PATH}"
-echo "-- Found workdir: ${WORKDIR}"
+echo "-- Found common-artifacts: ${RESOURCE_DIR}"
TESTED=()
PASSED=()
FAILED=()
-pushd "${WORKDIR}"
+pushd ${WORKDIR}
while [[ $# -ne 0 ]]; do
PREFIX="$1"; shift
@@ -40,7 +41,7 @@ while [[ $# -ne 0 ]]; do
cat > "${PREFIX}.log" <(
exec 2>&1
- echo "-- Found tflite: ${PREFIX}.tflite"
+ echo "-- Found circle: ${PREFIX}.opt.circle"
# Exit immediately if any command fails
set -e
@@ -55,7 +56,7 @@ while [[ $# -ne 0 ]]; do
set +x
# (COMPILED_FILE, INSPECT_PROG_PATH, VERIFY_PROG_PATH, ERROR_LOG) must be set for rule-lib.sh
- COMPILED_FILE="${WORKDIR}/${PREFIX}.opt.circle"
+ COMPILED_FILE="${PREFIX}.opt.circle"
INSPECT_PROG_PATH=${CIRCLE_INSPECT_PATH}
VERIFY_PROG_PATH=${CIRCLE_VERIFY_PATH}
ERROR_LOG="${PREFIX}.error"
@@ -66,7 +67,7 @@ while [[ $# -ne 0 ]]; do
trap 'echo "** ERROR **" ; cat "${ERROR_LOG}"' ERR
source rule-lib.sh
- source "${PREFIX}.rule"
+ source "${RESOURCE_DIR}/${PREFIX}.rule"
# unset
trap - ERR
diff --git a/compiler/circle2circle/CMakeLists.txt b/compiler/circle2circle/CMakeLists.txt
index 7b2bf9b02..f60c896d8 100644
--- a/compiler/circle2circle/CMakeLists.txt
+++ b/compiler/circle2circle/CMakeLists.txt
@@ -19,6 +19,7 @@ target_link_libraries(circle2circle luci_service)
target_link_libraries(circle2circle luci_pass)
target_link_libraries(circle2circle luci_export)
target_link_libraries(circle2circle arser)
+target_link_libraries(circle2circle vconone)
install(TARGETS circle2circle DESTINATION bin)
@@ -44,3 +45,4 @@ target_link_libraries(circle2circle_test luci_service)
target_link_libraries(circle2circle_test luci_pass)
target_link_libraries(circle2circle_test luci_export)
target_link_libraries(circle2circle_test arser)
+target_link_libraries(circle2circle_test vconone)
diff --git a/compiler/circle2circle/requires.cmake b/compiler/circle2circle/requires.cmake
index 8cbb90dbf..36a9efd16 100644
--- a/compiler/circle2circle/requires.cmake
+++ b/compiler/circle2circle/requires.cmake
@@ -9,3 +9,4 @@ require("hermes")
require("hermes-std")
require("luci")
require("arser")
+require("vconone")
diff --git a/compiler/circle2circle/src/Circle2Circle.cpp b/compiler/circle2circle/src/Circle2Circle.cpp
index 6888d26e3..849597b46 100644
--- a/compiler/circle2circle/src/Circle2Circle.cpp
+++ b/compiler/circle2circle/src/Circle2Circle.cpp
@@ -26,6 +26,7 @@
#include <oops/InternalExn.h>
#include <arser/arser.h>
+#include <vconone/vconone.h>
#include <functional>
#include <iostream>
@@ -34,6 +35,12 @@
using Algorithms = luci::CircleOptimizer::Options::Algorithm;
using AlgorithmParameters = luci::CircleOptimizer::Options::AlgorithmParameters;
+void print_version(void)
+{
+ std::cout << "circle2circle version " << vconone::get_string() << std::endl;
+ std::cout << vconone::get_copyright() << std::endl;
+}
+
int entry(int argc, char **argv)
{
// Simple argument parser (based on map)
@@ -44,6 +51,13 @@ int entry(int argc, char **argv)
arser::Arser arser("circle2circle provides circle model optimization and transformations");
+ arser.add_argument("--version")
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("Show version information and exit")
+ .exit_with(print_version);
+
arser.add_argument("--all").nargs(0).required(false).default_value(false).help(
"Enable all optimize options");
diff --git a/compiler/circlechef/CMakeLists.txt b/compiler/circlechef/CMakeLists.txt
index cba7d0a4e..3e2ddcbb3 100644
--- a/compiler/circlechef/CMakeLists.txt
+++ b/compiler/circlechef/CMakeLists.txt
@@ -18,4 +18,6 @@ add_subdirectory(core)
add_subdirectory(circle)
# Tools
add_subdirectory(tools)
-add_subdirectory(tests)
+if(ENABLE_TEST)
+ add_subdirectory(tests)
+endif(ENABLE_TEST)
diff --git a/compiler/circlechef/circle/src/RecipeChef.cpp b/compiler/circlechef/circle/src/RecipeChef.cpp
index 17ef1be6e..51326c7f8 100644
--- a/compiler/circlechef/circle/src/RecipeChef.cpp
+++ b/compiler/circlechef/circle/src/RecipeChef.cpp
@@ -181,6 +181,8 @@ std::unique_ptr<ModelRecipe> generate_recipe(const circle::Model *model)
for (uint32_t idx = 0; idx < quant->zero_point()->size(); ++idx)
chef_quant->add_zero_point(quant->zero_point()->Get(idx));
}
+ circlechef::TensorQuantization *chef_quant = operand->mutable_quant();
+ chef_quant->set_quantized_dimension(quant->quantized_dimension());
}
}
diff --git a/compiler/circlechef/core/src/ModelChef.cpp b/compiler/circlechef/core/src/ModelChef.cpp
index 76aeacdd9..d81467d68 100644
--- a/compiler/circlechef/core/src/ModelChef.cpp
+++ b/compiler/circlechef/core/src/ModelChef.cpp
@@ -413,6 +413,7 @@ template <typename T> void cook_graph(const T &graph, CookParams &cp)
quant_builder.add_min(quant_min);
quant_builder.add_scale(quant_scale);
quant_builder.add_zero_point(quant_zero_point);
+ quant_builder.add_quantized_dimension(quant.quantized_dimension());
// Update QuantizationParameters Index
quant_index = quant_builder.Finish();
diff --git a/compiler/circlechef/proto/circlechef.proto b/compiler/circlechef/proto/circlechef.proto
index b8c009b38..3e5e6b168 100644
--- a/compiler/circlechef/proto/circlechef.proto
+++ b/compiler/circlechef/proto/circlechef.proto
@@ -35,6 +35,7 @@ message TensorQuantization {
repeated float max = 2;
repeated float scale = 3;
repeated int64 zero_point = 4;
+ optional int32 quantized_dimension = 5 [default = 0];
}
message Operand {
diff --git a/compiler/circlechef/tools/file/Driver.cpp b/compiler/circlechef/tools/file/Driver.cpp
index a15da4002..bcc0c7ae9 100644
--- a/compiler/circlechef/tools/file/Driver.cpp
+++ b/compiler/circlechef/tools/file/Driver.cpp
@@ -41,7 +41,7 @@ int entry(int argc, char **argv)
{
std::cout << err.what() << std::endl;
std::cout << arser;
- return 0;
+ return 255;
}
int32_t model_version = 1;
diff --git a/compiler/circlechef/tools/reverse/Driver.cpp b/compiler/circlechef/tools/reverse/Driver.cpp
index 9c0b9ea24..8a2b85fc7 100644
--- a/compiler/circlechef/tools/reverse/Driver.cpp
+++ b/compiler/circlechef/tools/reverse/Driver.cpp
@@ -38,7 +38,7 @@ int entry(int argc, char **argv)
{
std::cout << err.what() << std::endl;
std::cout << arser;
- return 0;
+ return 255;
}
std::string circle_path = arser.get<std::string>("circle");
diff --git a/compiler/circledump/driver/Driver.cpp b/compiler/circledump/driver/Driver.cpp
index b8f561fee..657f24fe0 100644
--- a/compiler/circledump/driver/Driver.cpp
+++ b/compiler/circledump/driver/Driver.cpp
@@ -33,7 +33,7 @@ int entry(int argc, char **argv)
{
std::cout << err.what() << '\n';
std::cout << arser;
- return 0;
+ return 255;
}
std::string circle_path = arser.get<std::string>("circle");
diff --git a/compiler/circledump/src/OpPrinter.cpp b/compiler/circledump/src/OpPrinter.cpp
index 2c0320396..3294bb23d 100644
--- a/compiler/circledump/src/OpPrinter.cpp
+++ b/compiler/circledump/src/OpPrinter.cpp
@@ -593,6 +593,20 @@ public:
}
};
+class UniquePrinter : public OpPrinter
+{
+public:
+ void options(const circle::Operator *op, std::ostream &os) const override
+ {
+ if (auto *params = op->builtin_options_as_UniqueOptions())
+ {
+ os << " ";
+ os << "idx_out_type(" << EnumNameTensorType(params->idx_out_type()) << ") ";
+ os << std::endl;
+ }
+ }
+};
+
class WhilePrinter : public OpPrinter
{
public:
@@ -710,9 +724,11 @@ OpPrinterRegistry::OpPrinterRegistry()
_op_map[circle::BuiltinOperator_MAX_POOL_2D] = make_unique<Pool2DPrinter>();
_op_map[circle::BuiltinOperator_MIRROR_PAD] = make_unique<MirrorPadPrinter>();
_op_map[circle::BuiltinOperator_MUL] = make_unique<MulPrinter>();
+ // There is no Option for NON_MAX_SUPPRESSION_V4
_op_map[circle::BuiltinOperator_ONE_HOT] = make_unique<OneHotPrinter>();
_op_map[circle::BuiltinOperator_PACK] = make_unique<PackPrinter>();
// There is no Option for PAD
+ // There is no Option for PADV2
// There is no Option for PRELU
// There is no Option for RELU
// There is no Option for RELU6
@@ -744,6 +760,7 @@ OpPrinterRegistry::OpPrinterRegistry()
_op_map[circle::BuiltinOperator_SUM] = make_unique<ReducerPrinter>();
_op_map[circle::BuiltinOperator_TRANSPOSE_CONV] = make_unique<TransposeConvPrinter>();
// There is no Option for TOPK_V2
+ _op_map[circle::BuiltinOperator_UNIQUE] = make_unique<UniquePrinter>();
_op_map[circle::BuiltinOperator_WHILE] = make_unique<WhilePrinter>();
_op_map[circle::BuiltinOperator_CUSTOM] = make_unique<CustomOpPrinter>();
diff --git a/compiler/common-artifacts/CMakeLists.txt b/compiler/common-artifacts/CMakeLists.txt
index ee4191d73..ef50e8d43 100644
--- a/compiler/common-artifacts/CMakeLists.txt
+++ b/compiler/common-artifacts/CMakeLists.txt
@@ -13,30 +13,47 @@ if(${PYTHON_VERSION_MINOR} LESS 3)
endif()
# Create python virtual environment with tensorflow 1.13.2
-set(VIRTUALENV_OVERLAY "${NNCC_OVERLAY_DIR}/venv_1_13_2")
+set(VIRTUALENV_OVERLAY_TF_1_13_2 "${NNCC_OVERLAY_DIR}/venv_1_13_2")
+
+# Create python virtual environment with tensorflow 2.3.0
+set(VIRTUALENV_OVERLAY_TF_2_3_0 "${NNCC_OVERLAY_DIR}/venv_2_3_0")
+
+add_custom_command(
+ OUTPUT ${VIRTUALENV_OVERLAY_TF_1_13_2}
+ COMMAND ${PYTHON_EXECUTABLE} -m venv ${VIRTUALENV_OVERLAY_TF_1_13_2}
+)
add_custom_command(
- OUTPUT ${VIRTUALENV_OVERLAY}
- COMMAND ${PYTHON_EXECUTABLE} -m venv ${VIRTUALENV_OVERLAY}
+ OUTPUT ${VIRTUALENV_OVERLAY_TF_2_3_0}
+ COMMAND ${PYTHON_EXECUTABLE} -m venv ${VIRTUALENV_OVERLAY_TF_2_3_0}
)
# Create requirements.txt and install required pip packages
set(REQUIREMENTS_FILE "requirements.txt")
-set(REQUIREMENTS_OVERLAY_PATH "${NNCC_OVERLAY_DIR}/${REQUIREMENTS_FILE}")
+set(REQUIREMENTS_OVERLAY_PATH_TF_1_13_2 "${VIRTUALENV_OVERLAY_TF_1_13_2}/${REQUIREMENTS_FILE}")
+set(REQUIREMENTS_OVERLAY_PATH_TF_2_3_0 "${VIRTUALENV_OVERLAY_TF_2_3_0}/${REQUIREMENTS_FILE}")
add_custom_command(
- OUTPUT ${REQUIREMENTS_OVERLAY_PATH}
- COMMAND ${CMAKE_COMMAND} -E echo "tensorflow==1.13.2" > ${REQUIREMENTS_OVERLAY_PATH}
- COMMAND ${VIRTUALENV_OVERLAY}/bin/python -m pip --default-timeout=1000 install --upgrade pip setuptools
- COMMAND ${VIRTUALENV_OVERLAY}/bin/python -m pip --default-timeout=1000 install -r ${REQUIREMENTS_OVERLAY_PATH} --upgrade
- DEPENDS ${VIRTUALENV_OVERLAY} ${REQUIREMENTS_OVERLAY_PATH}
+ OUTPUT ${REQUIREMENTS_OVERLAY_PATH_TF_1_13_2}
+ COMMAND ${CMAKE_COMMAND} -E echo "tensorflow==1.13.2" > ${REQUIREMENTS_OVERLAY_PATH_TF_1_13_2}
+ COMMAND ${VIRTUALENV_OVERLAY_TF_1_13_2}/bin/python -m pip --default-timeout=1000 install --upgrade pip setuptools
+ COMMAND ${VIRTUALENV_OVERLAY_TF_1_13_2}/bin/python -m pip --default-timeout=1000 install -r ${REQUIREMENTS_OVERLAY_PATH_TF_1_13_2} --upgrade
+ DEPENDS ${VIRTUALENV_OVERLAY_TF_1_13_2}
)
-add_custom_target(common_artifacts_python_deps ALL
- DEPENDS ${VIRTUALENV_OVERLAY} ${REQUIREMENTS_OVERLAY_PATH}
+add_custom_command(
+ OUTPUT ${REQUIREMENTS_OVERLAY_PATH_TF_2_3_0}
+ COMMAND ${CMAKE_COMMAND} -E remove -f ${REQUIREMENTS_OVERLAY_PATH_TF_2_3_0}
+ COMMAND ${CMAKE_COMMAND} -E echo "tensorflow-cpu==2.3.0" >> ${REQUIREMENTS_OVERLAY_PATH_TF_2_3_0}
+ COMMAND ${CMAKE_COMMAND} -E echo "flatbuffers==1.12" >> ${REQUIREMENTS_OVERLAY_PATH_TF_2_3_0}
+ COMMAND ${VIRTUALENV_OVERLAY_TF_2_3_0}/bin/python -m pip --default-timeout=1000 install --upgrade pip setuptools
+ COMMAND ${VIRTUALENV_OVERLAY_TF_2_3_0}/bin/python -m pip --default-timeout=1000 install -r ${REQUIREMENTS_OVERLAY_PATH_TF_2_3_0} --upgrade
+ DEPENDS ${VIRTUALENV_OVERLAY_TF_2_3_0}
)
-# TODO Create python virtual environment with tensorflow 2.3.0-rc0
+add_custom_target(common_artifacts_python_deps ALL
+ DEPENDS ${VIRTUALENV_OVERLAY_TF_1_13_2} ${VIRTUALENV_OVERLAY_TF_2_3_0} ${REQUIREMENTS_OVERLAY_PATH_TF_1_13_2} ${REQUIREMENTS_OVERLAY_PATH_TF_2_3_0}
+)
#[[ Generate common resources ]]
# TODO add pbtxt
@@ -52,6 +69,7 @@ set(SOURCES src/TestDataGenerator.cpp)
add_executable(testDataGenerator ${SOURCES})
target_include_directories(testDataGenerator PRIVATE ${HDF5_INCLUDE_DIRS})
target_link_libraries(testDataGenerator PRIVATE ${HDF5_CXX_LIBRARIES})
+target_link_libraries(testDataGenerator PRIVATE arser)
target_link_libraries(testDataGenerator PRIVATE foder)
target_link_libraries(testDataGenerator PRIVATE luci_import)
target_link_libraries(testDataGenerator PRIVATE luci_interpreter)
diff --git a/compiler/common-artifacts/exclude.lst b/compiler/common-artifacts/exclude.lst
index b614b7182..fe9933ae0 100644
--- a/compiler/common-artifacts/exclude.lst
+++ b/compiler/common-artifacts/exclude.lst
@@ -5,9 +5,12 @@
#[[ optimize : Exclude from circle optimization(circle2circle) ]]
## TensorFlowLiteRecipes
-optimize(ReLU6_000)
-optimize(Where_000)
-optimize(Where_001)
+optimize(Unique_000)
+optimize(Unique_001)
+optimize(Unique_002)
+optimize(Unique_003)
+optimize(Unique_U8_000)
+optimize(Unique_U8_001)
## CircleRecipes
@@ -46,6 +49,7 @@ tcgenerate(DepthToSpace_000)
tcgenerate(DepthwiseConv2D_001) # runtime doesn't support dilation
tcgenerate(DepthwiseConv2D_003) # runtime doesn't support dilation
tcgenerate(DepthwiseConv2D_U8_000)
+tcgenerate(DepthwiseConv2D_U8_001) # luci-interpreter doesn't support channel-wise quantization yet
tcgenerate(Div_000)
tcgenerate(ELU_000)
tcgenerate(Equal_000)
@@ -90,13 +94,15 @@ tcgenerate(Maximum_000)
tcgenerate(MaxPool2D_U8_000)
tcgenerate(Mean_U8_000)
tcgenerate(Minimum_000)
+tcgenerate(NonMaxSuppressionV4_000)
+tcgenerate(NonMaxSuppressionV4_001)
tcgenerate(MirrorPad_000)
tcgenerate(Mul_U8_000)
tcgenerate(Neg_000)
tcgenerate(Net_Dangle_001)
tcgenerate(Net_InstanceNorm_001)
tcgenerate(Net_InstanceNorm_002)
-tcgenerate(Net_ZeroDim_001) # fix luci
+tcgenerate(Net_ZeroDim_001) # luci-interpreter doesn't support zero dim
tcgenerate(NotEqual_000)
tcgenerate(OneHot_000)
tcgenerate(OneHot_001)
@@ -105,6 +111,7 @@ tcgenerate(OneHot_003)
tcgenerate(Pack_000)
tcgenerate(Pack_U8_000)
tcgenerate(Pad_U8_000)
+tcgenerate(PadV2_000)
tcgenerate(Pow_000)
tcgenerate(PRelu_000)
tcgenerate(Range_000)
@@ -120,11 +127,12 @@ tcgenerate(ReduceProd_001)
tcgenerate(ReduceProd_002)
tcgenerate(ReduceProd_003)
tcgenerate(ReLU_000)
-tcgenerate(ReLU6_000) # luci NYI
+tcgenerate(ReLU6_000)
tcgenerate(ReLUN1To1_000)
-tcgenerate(Reshape_003) # fix luci
+tcgenerate(Reshape_003) # luci-interpreter doesn't support reshape without built-in option
tcgenerate(Reshape_U8_000)
tcgenerate(ResizeBilinear_000)
+tcgenerate(ResizeBilinear_U8_000) # luci-interpreter
tcgenerate(ResizeNearestNeighbor_000)
tcgenerate(ReverseSequence_000)
tcgenerate(ReverseV2_000)
@@ -148,7 +156,7 @@ tcgenerate(SpaceToBatchND_002)
tcgenerate(SpaceToBatchND_003)
tcgenerate(SpaceToDepth_000)
tcgenerate(SparseToDense_000)
-tcgenerate(SplitV_000) # fix luci
+tcgenerate(SplitV_000)
tcgenerate(Sqrt_000)
tcgenerate(Square_000)
tcgenerate(SquaredDifference_000)
@@ -164,22 +172,21 @@ tcgenerate(Sum_001)
tcgenerate(Tanh_000)
tcgenerate(Tile_000)
tcgenerate(Tile_U8_000)
-tcgenerate(TopKV2_000) # fix luci
-tcgenerate(TopKV2_001) # fix luci
-tcgenerate(TransposeConv_000) # fix interpreter
+tcgenerate(TopKV2_000)
+tcgenerate(TopKV2_001)
tcgenerate(Unique_000)
tcgenerate(Unique_001)
tcgenerate(Unique_002)
tcgenerate(Unique_003)
tcgenerate(Unique_U8_000)
tcgenerate(Unique_U8_001)
-tcgenerate(Where_000) # luci NYI
-tcgenerate(Where_001) # luci NYI
-tcgenerate(While_000) # fix luci
+tcgenerate(Where_000)
+tcgenerate(Where_001)
+tcgenerate(While_000)
tcgenerate(While_001)
tcgenerate(While_002)
tcgenerate(While_003)
-tcgenerate(YUV_TO_RGB_000) # fix luci
+tcgenerate(YUV_TO_RGB_000)
tcgenerate(YUV_TO_RGB_U8_000)
tcgenerate(ZerosLike_000)
diff --git a/compiler/common-artifacts/requires.cmake b/compiler/common-artifacts/requires.cmake
index 8c27565cf..d7bed21fe 100644
--- a/compiler/common-artifacts/requires.cmake
+++ b/compiler/common-artifacts/requires.cmake
@@ -1,3 +1,4 @@
+require("arser")
require("circle2circle")
require("circlechef")
require("foder")
diff --git a/compiler/common-artifacts/src/TestDataGenerator.cpp b/compiler/common-artifacts/src/TestDataGenerator.cpp
index 739300d18..7a07dd88e 100644
--- a/compiler/common-artifacts/src/TestDataGenerator.cpp
+++ b/compiler/common-artifacts/src/TestDataGenerator.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <arser/arser.h>
#include <foder/FileLoader.h>
#include <luci/Importer.h>
#include <luci_interpreter/Interpreter.h>
@@ -62,10 +63,9 @@ template <typename T> void geneate_random_data(std::mt19937 &gen, void *data, ui
}
}
-void fill_random_data(void *data, uint32_t size, loco::DataType dtype)
+void fill_random_data(void *data, uint32_t size, loco::DataType dtype, uint32_t seed)
{
- std::random_device rd; // used to obtain a seed for the random number engine
- std::mt19937 gen(rd()); // standard mersenne_twister_engine seeded with rd()
+ std::mt19937 gen(seed); // standard mersenne_twister_engine seeded with rd()
switch (dtype)
{
@@ -90,7 +90,25 @@ void fill_random_data(void *data, uint32_t size, loco::DataType dtype)
int entry(int argc, char **argv)
{
- std::string circle_file{argv[1]};
+ arser::Arser arser;
+ arser.add_argument("circle").type(arser::DataType::STR).help("Circle file you want to test");
+ arser.add_argument("--fixed_seed")
+ .required(false)
+ .nargs(0)
+ .help("Put a fixed seed into the random number generator");
+
+ try
+ {
+ arser.parse(argc, argv);
+ }
+ catch (const std::runtime_error &err)
+ {
+ std::cout << err.what() << std::endl;
+ std::cout << arser;
+ return 255;
+ }
+
+ std::string circle_file = arser.get<std::string>("circle");
size_t last_dot_index = circle_file.find_last_of(".");
std::string prefix = circle_file.substr(0, last_dot_index);
@@ -136,6 +154,7 @@ int entry(int argc, char **argv)
std::unique_ptr<H5::Group> output_value_group =
std::make_unique<H5::Group>(output_file.createGroup("value"));
+ std::random_device rd; // used to obtain a seed for the random number engine
uint32_t input_index = 0;
for (uint32_t g = 0; g < circle_model->subgraphs()->size(); g++)
{
@@ -174,7 +193,10 @@ int entry(int argc, char **argv)
std::vector<int8_t> data(byte_size);
// generate random data
- fill_random_data(data.data(), data_size, input_node->dtype());
+ if (arser["--fixed_seed"])
+ fill_random_data(data.data(), data_size, input_node->dtype(), 0);
+ else
+ fill_random_data(data.data(), data_size, input_node->dtype(), rd());
dataset->write(data.data(), dtype);
diff --git a/compiler/hermes/src/hermes.test.cpp b/compiler/hermes/src/hermes.test.cpp
index 2cbc0939d..ea7ef65d8 100644
--- a/compiler/hermes/src/hermes.test.cpp
+++ b/compiler/hermes/src/hermes.test.cpp
@@ -18,7 +18,28 @@
#include <gtest/gtest.h>
-TEST(HermesTest, simple_usecase)
+namespace
{
- // TO BE FILLED
+
+class Logger final : public hermes::Source
+{
+public:
+ Logger(hermes::Context *ctx);
+ ~Logger();
+};
+
+Logger::Logger(hermes::Context *ctx) { activate(ctx->sources(), ctx->bus()); }
+Logger::~Logger() { deactivate(); }
+
+} // namespace
+
+TEST(HermesTest, logger_constructor_NEG)
+{
+ hermes::Context context;
+ // we expect segmentfault from nullptr->sources()
+ ASSERT_DEATH(Logger logger(&context), "");
+
+ SUCCEED();
}
+
+// TODO add HermesTest simple_usecase
diff --git a/compiler/locomotiv/src/Node/BiasEncode.test.cpp b/compiler/locomotiv/src/Node/BiasEncode.test.cpp
index cdb255ccb..4680f5c5a 100644
--- a/compiler/locomotiv/src/Node/BiasEncode.test.cpp
+++ b/compiler/locomotiv/src/Node/BiasEncode.test.cpp
@@ -90,6 +90,16 @@ template <typename T> void test()
}
} // namespace
-TEST(NodeExecution_BiasEncode, s32) { test<int32_t>(); }
+TEST(NodeExecution_BiasEncode, s32)
+{
+ test<int32_t>();
+
+ SUCCEED();
+}
-TEST(NodeExecution_BiasEncode, f32) { test<float>(); }
+TEST(NodeExecution_BiasEncode, f32)
+{
+ test<float>();
+
+ SUCCEED();
+}
diff --git a/compiler/locomotiv/src/Node/MatMul.test.cpp b/compiler/locomotiv/src/Node/MatMul.test.cpp
index f1f3a52d3..7d942e1d0 100644
--- a/compiler/locomotiv/src/Node/MatMul.test.cpp
+++ b/compiler/locomotiv/src/Node/MatMul.test.cpp
@@ -142,6 +142,8 @@ TEST(NodeExecution_MatMul, f32_2x3_3x3)
};
run_test<float>(lhs, rhs, out, Shape{2, 3}, Shape{3, 3}, Shape{2, 3}, loco::DataType::FLOAT32);
+
+ SUCCEED();
}
/* from the code below:
@@ -183,6 +185,8 @@ TEST(NodeExecution_MatMul, s32_4x2_2x6)
};
run_test<int32_t>(lhs, rhs, out, Shape{4, 2}, Shape{2, 6}, Shape{4, 6}, loco::DataType::S32);
+
+ SUCCEED();
}
// clang-format on
diff --git a/compiler/locop/src/FormattedGraph.test.cpp b/compiler/locop/src/FormattedGraph.test.cpp
index c9808d3a2..aff9ebe5f 100644
--- a/compiler/locop/src/FormattedGraph.test.cpp
+++ b/compiler/locop/src/FormattedGraph.test.cpp
@@ -28,6 +28,8 @@ TEST(LinearV1FormatterTest, simple)
// TODO Validate the output (when the implementation becomes stable)
std::cout << locop::fmt<locop::LinearV1>(g) << std::endl;
+
+ SUCCEED();
}
TEST(LinearV1FormatterTest, user_defined_node_summary_builder)
diff --git a/compiler/locop/src/FormattedTensorShape.test.cpp b/compiler/locop/src/FormattedTensorShape.test.cpp
index 0f0017ab4..fc85df3a6 100644
--- a/compiler/locop/src/FormattedTensorShape.test.cpp
+++ b/compiler/locop/src/FormattedTensorShape.test.cpp
@@ -30,4 +30,6 @@ TEST(FormattedTensorShapeTest, BracketFormat)
tensor_shape->dim(0) = 4;
std::cout << fmt<TensorShapeFormat::Bracket>(tensor_shape.get()) << std::endl;
+
+ SUCCEED();
}
diff --git a/compiler/luci-interpreter/include/luci_interpreter/core/Tensor.h b/compiler/luci-interpreter/include/luci_interpreter/core/Tensor.h
index 998789882..4ac3d8660 100644
--- a/compiler/luci-interpreter/include/luci_interpreter/core/Tensor.h
+++ b/compiler/luci-interpreter/include/luci_interpreter/core/Tensor.h
@@ -79,12 +79,11 @@ private:
//
// Note that due to historical and performance reasons, per-tensor quantization uses unsigned
// integer types, while per-channel uses signed types assuming 'zero_point' == 0.
-//
-// TODO Add 'quantized_dimension' field for per-channel case when IR provides it.
struct AffineQuantization
{
std::vector<float> scale;
std::vector<int32_t> zero_point;
+ int32_t quantized_dimension;
};
class Tensor
@@ -108,6 +107,12 @@ public:
return _quantization.zero_point[0];
}
+ const std::vector<float> &scales() const { return _quantization.scale; }
+
+ const std::vector<int32_t> &zero_points() const { return _quantization.zero_point; }
+
+ int32_t quantized_dimension() const { return _quantization.quantized_dimension; }
+
template <typename T> const T *data() const { return reinterpret_cast<const T *>(_data.get()); }
template <typename T> T *data() { return reinterpret_cast<T *>(_data.get()); }
diff --git a/compiler/luci-interpreter/src/core/KernelParams.h b/compiler/luci-interpreter/src/core/KernelParams.h
index a32e0d4a5..65d119761 100644
--- a/compiler/luci-interpreter/src/core/KernelParams.h
+++ b/compiler/luci-interpreter/src/core/KernelParams.h
@@ -56,6 +56,11 @@ struct Conv2DParams
Activation activation;
};
+struct DepthToSpaceParams
+{
+ int block_size;
+};
+
struct DepthwiseConv2DParams
{
Padding padding;
diff --git a/compiler/luci-interpreter/src/kernels/Add.cpp b/compiler/luci-interpreter/src/kernels/Add.cpp
index 9b9334792..9ed155e94 100644
--- a/compiler/luci-interpreter/src/kernels/Add.cpp
+++ b/compiler/luci-interpreter/src/kernels/Add.cpp
@@ -36,7 +36,10 @@ Add::Add(const Tensor *input1, const Tensor *input2, Tensor *output, const AddPa
void Add::configure()
{
- assert(input1()->element_type() == input2()->element_type());
+ if (input1()->element_type() != input2()->element_type())
+ {
+ throw std::runtime_error("Input Tensor Data Type Mismatch.");
+ }
output()->resize(calculateShapeForBroadcast(input1()->shape(), input2()->shape()));
}
diff --git a/compiler/luci-interpreter/src/kernels/Add.test.cpp b/compiler/luci-interpreter/src/kernels/Add.test.cpp
index 54e1cc672..705b648c8 100644
--- a/compiler/luci-interpreter/src/kernels/Add.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/Add.test.cpp
@@ -169,6 +169,33 @@ TEST(AddTest, Float)
}
}
+TEST(AddTest, Input_Output_Type_NEG)
+{
+ Tensor input1_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f});
+ Tensor input2_tensor = makeInputTensor<DataType::S32>({1}, {2});
+ Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+ AddParams params{};
+ params.activation = Activation::RELU;
+
+ Add kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
+ EXPECT_ANY_THROW(kernel.configure());
+}
+
+TEST(AddTest, Invalid_Input_Type_NEG)
+{
+ Tensor input1_tensor = makeInputTensor<DataType::S64>({1}, {1});
+ Tensor input2_tensor = makeInputTensor<DataType::S64>({1}, {2});
+ Tensor output_tensor = makeOutputTensor(DataType::S64);
+
+ AddParams params{};
+ params.activation = Activation::RELU;
+
+ Add kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
+ kernel.configure();
+ EXPECT_ANY_THROW(kernel.execute());
+}
+
} // namespace
} // namespace kernels
} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/CMakeLists.txt b/compiler/luci-interpreter/src/kernels/CMakeLists.txt
index fe3623135..a1fd1deaf 100644
--- a/compiler/luci-interpreter/src/kernels/CMakeLists.txt
+++ b/compiler/luci-interpreter/src/kernels/CMakeLists.txt
@@ -12,6 +12,8 @@ set(SOURCES
Concatenation.cpp
Conv2D.h
Conv2D.cpp
+ DepthToSpace.h
+ DepthToSpace.cpp
DepthwiseConv2D.h
DepthwiseConv2D.cpp
Elu.h
@@ -40,6 +42,10 @@ set(SOURCES
Pad.cpp
Reshape.h
Reshape.cpp
+ Reverse.h
+ Reverse.cpp
+ Slice.h
+ Slice.cpp
Softmax.h
Softmax.cpp
SpaceToDepth.h
@@ -77,6 +83,7 @@ set(TEST_SOURCES
AveragePool2D.test.cpp
Concatenation.test.cpp
Conv2D.test.cpp
+ DepthToSpace.test.cpp
DepthwiseConv2D.test.cpp
Elu.test.cpp
FullyConnected.test.cpp
@@ -91,6 +98,8 @@ set(TEST_SOURCES
Mul.test.cpp
Pad.test.cpp
Reshape.test.cpp
+ Reverse.test.cpp
+ Slice.test.cpp
Softmax.test.cpp
SpaceToDepth.test.cpp
Split.test.cpp
diff --git a/compiler/luci-interpreter/src/kernels/DepthToSpace.cpp b/compiler/luci-interpreter/src/kernels/DepthToSpace.cpp
new file mode 100644
index 000000000..cab63e26d
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/DepthToSpace.cpp
@@ -0,0 +1,90 @@
+/*
+ * 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 "DepthToSpace.h"
+#include "Utils.h"
+#include <tensorflow/lite/kernels/internal/optimized/optimized_ops.h>
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+
+DepthToSpace::DepthToSpace(const Tensor *input, Tensor *output, const DepthToSpaceParams &params)
+ : KernelWithParams<DepthToSpaceParams>({input}, {output}, params)
+{
+}
+
+void DepthToSpace::configure()
+{
+ if (input()->shape().num_dims() != 4)
+ {
+ throw std::runtime_error("Invalid input num_dims.");
+ }
+ if (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)
+ {
+ throw std::runtime_error("Invalid output type");
+ }
+ if (input()->element_type() != output()->element_type())
+ {
+ throw std::runtime_error("Type mismatch on input and output.");
+ }
+ 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;
+
+ assert(input_height == output_height / block_size);
+ assert(input_width == output_width / block_size);
+ assert(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;
+
+ output()->resize(output_shape);
+}
+
+void DepthToSpace::execute() const
+{
+ tflite::DepthToSpaceParams op_params;
+ op_params.block_size = params().block_size;
+ switch (input()->element_type())
+ {
+ case DataType::FLOAT32:
+ tflite::optimized_ops::DepthToSpace(op_params, getTensorShape(input()),
+ getTensorData<float>(input()), getTensorShape(output()),
+ getTensorData<float>(output()));
+ break;
+ case DataType::U8:
+ tflite::optimized_ops::DepthToSpace(op_params, getTensorShape(input()),
+ getTensorData<uint8_t>(input()), getTensorShape(output()),
+ getTensorData<uint8_t>(output()));
+ break;
+ default:
+ throw std::runtime_error("Unsupported Type.");
+ }
+}
+
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/DepthToSpace.h b/compiler/luci-interpreter/src/kernels/DepthToSpace.h
new file mode 100644
index 000000000..63ce37610
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/DepthToSpace.h
@@ -0,0 +1,45 @@
+/*
+ * 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
diff --git a/compiler/luci-interpreter/src/kernels/DepthToSpace.test.cpp b/compiler/luci-interpreter/src/kernels/DepthToSpace.test.cpp
new file mode 100644
index 000000000..1b805702d
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/DepthToSpace.test.cpp
@@ -0,0 +1,60 @@
+/*
+ * 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/DepthToSpace.h"
+#include "kernels/TestUtils.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+namespace
+{
+
+using namespace testing;
+
+template <typename T> class DepthToSpaceTest : public ::testing::Test
+{
+};
+
+using DataTypes = ::testing::Types<float, uint8_t>;
+TYPED_TEST_CASE(DepthToSpaceTest, DataTypes);
+
+TYPED_TEST(DepthToSpaceTest, SimpleCase)
+{
+ 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);
+ Tensor output_tensor = makeOutputTensor(getElementType<TypeParam>());
+
+ DepthToSpaceParams params{};
+ params.block_size = 2;
+
+ DepthToSpace kernel = DepthToSpace(&input_tensor, &output_tensor, params);
+ kernel.configure();
+ kernel.execute();
+
+ EXPECT_THAT(extractTensorData<TypeParam>(output_tensor),
+ ::testing::ElementsAreArray(output_data));
+ EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
+}
+
+} // namespace
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/L2Normalize.test.cpp b/compiler/luci-interpreter/src/kernels/L2Normalize.test.cpp
index fad450d66..f53eaca94 100644
--- a/compiler/luci-interpreter/src/kernels/L2Normalize.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/L2Normalize.test.cpp
@@ -45,12 +45,9 @@ TEST(L2NormalizeTest, Float)
ElementsAreArray(ArrayFloatNear(ref_output_data)));
}
-TEST(L2NormalizeTest, Uint8Quantized)
-{
- // TODO
- // Implement GetDequantizedOutput Function.
- // Create Test for Uint8 Case
-}
+// TODO Uint8Quantized
+// Implement GetDequantizedOutput Function.
+// Create Test for Uint8 Case
} // namespace
} // namespace kernels
diff --git a/compiler/luci-interpreter/src/kernels/LeakyRelu.test.cpp b/compiler/luci-interpreter/src/kernels/LeakyRelu.test.cpp
index b0c06e7a3..c79d3d6bc 100644
--- a/compiler/luci-interpreter/src/kernels/LeakyRelu.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/LeakyRelu.test.cpp
@@ -61,15 +61,14 @@ TEST(LeakReluTest, FloatSimple)
1.0f, -0.5f, -1.0f, // Row 2
},
/*alpha=*/0.5f, getElementType<float>());
-}
-TEST(LeakReluTest, Uint8Simple)
-{
- // TODO
- // Implement GetDequantizedOutput Function.
- // Create Test for Uint8 Case
+ SUCCEED();
}
+// TODO Uint8Simple
+// Implement GetDequantizedOutput Function.
+// Create Test for Uint8 Case
+
} // namespace
} // namespace kernels
} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/Logistic.test.cpp b/compiler/luci-interpreter/src/kernels/Logistic.test.cpp
index 17456a4a8..00feddf3d 100644
--- a/compiler/luci-interpreter/src/kernels/Logistic.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/Logistic.test.cpp
@@ -49,10 +49,8 @@ TEST(LogisticTest, Float)
// TODO make a Shape checking of output_tensor.
}
-TEST(LogisticTest, Uint8)
-{
- // Need to Implement GetDequantizedOutput Function.
-}
+// TODO Uint8
+// Need to Implement GetDequantizedOutput Function.
} // namespace
} // namespace kernels
diff --git a/compiler/luci-interpreter/src/kernels/Reverse.cpp b/compiler/luci-interpreter/src/kernels/Reverse.cpp
new file mode 100644
index 000000000..a46308412
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/Reverse.cpp
@@ -0,0 +1,81 @@
+/*
+ * 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/Reverse.h"
+#include "kernels/Utils.h"
+#include <tensorflow/lite/kernels/internal/reference/reference_ops.h>
+
+namespace luci_interpreter
+{
+
+namespace kernels
+{
+
+Reverse::Reverse(const Tensor *input, const Tensor *axes, Tensor *output)
+ : Kernel({input, axes}, {output})
+{
+}
+
+void Reverse::configure()
+{
+ assert(axes()->shape().num_dims() == 1);
+ assert(input()->shape().num_dims() >= axes()->shape().num_elements());
+ if (input()->element_type() != DataType::S32 && input()->element_type() != DataType::FLOAT32 &&
+ input()->element_type() != DataType::U8 && input()->element_type() != DataType::S16 &&
+ input()->element_type() != DataType::S64)
+ {
+ throw std::runtime_error("Unsupported input type.");
+ }
+ if (axes()->element_type() != DataType::S32)
+ {
+ throw std::runtime_error("Unsupported axes type.");
+ }
+ if (axes()->shape().num_elements() > 1)
+ {
+ throw std::runtime_error("Current implementation does not support more than 1 axis.");
+ }
+ int axis_value = getTensorData<int32_t>(axes())[0];
+ if (axis_value < 0 || axis_value >= input()->shape().num_dims())
+ {
+ throw std::runtime_error("Invalid axes value");
+ }
+ assert(input()->element_type() == output()->element_type());
+
+ output()->resize(input()->shape());
+}
+
+void Reverse::execute() const
+{
+ int axis_value = getTensorData<int32_t>(axes())[0];
+ switch (output()->element_type())
+ {
+ case DataType::FLOAT32:
+ tflite::reference_ops::Reverse<float>(axis_value, getTensorShape(input()),
+ getTensorData<float>(input()), getTensorShape(output()),
+ getTensorData<float>(output()));
+ break;
+ case DataType::U8:
+ tflite::reference_ops::Reverse<uint8_t>(
+ axis_value, getTensorShape(input()), getTensorData<uint8_t>(input()),
+ getTensorShape(output()), getTensorData<uint8_t>(output()));
+ break;
+ default:
+ throw std::runtime_error("Unsupported output type");
+ }
+}
+
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/Reverse.h b/compiler/luci-interpreter/src/kernels/Reverse.h
new file mode 100644
index 000000000..3489dae28
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/Reverse.h
@@ -0,0 +1,43 @@
+/*
+ * 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_REVERSE_H
+#define LUCI_INTERPRETER_KERNELS_REVERSE_H
+
+#include "core/Kernel.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+
+class Reverse : public Kernel
+{
+public:
+ Reverse(const Tensor *input, const Tensor *axes, Tensor *output);
+
+ 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;
+};
+
+} // namespace kernels
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_KERNELS_REVERSE_H
diff --git a/compiler/luci-interpreter/src/kernels/Reverse.test.cpp b/compiler/luci-interpreter/src/kernels/Reverse.test.cpp
new file mode 100644
index 000000000..5475a8bd3
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/Reverse.test.cpp
@@ -0,0 +1,66 @@
+/*
+ * 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/Reverse.h"
+#include "kernels/TestUtils.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+namespace
+{
+
+using namespace testing;
+
+template <typename T> class ReverseTest : public ::testing::Test
+{
+};
+
+using DataTypes = ::testing::Types<float, uint8_t>;
+TYPED_TEST_CASE(ReverseTest, DataTypes);
+
+TYPED_TEST(ReverseTest, MultiDimensions)
+{
+ // TypeParam
+ std::vector<TypeParam> 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};
+ Shape input_shape{4, 3, 2};
+ std::vector<int32_t> axis_data{1};
+ Shape axis_shape{1};
+
+ std::vector<TypeParam> output_data{5, 6, 3, 4, 1, 2, 11, 12, 9, 10, 7, 8,
+ 17, 18, 15, 16, 13, 14, 23, 24, 21, 22, 19, 20};
+ std::vector<int32_t> output_shape{4, 3, 2};
+
+ Tensor input_tensor = makeInputTensor<getElementType<TypeParam>()>(input_shape, input_data);
+ Tensor axis_tensor = makeInputTensor<DataType::S32>(axis_shape, axis_data);
+
+ Tensor output_tensor = makeOutputTensor(getElementType<TypeParam>());
+
+ Reverse kernel = Reverse(&input_tensor, &axis_tensor, &output_tensor);
+ kernel.configure();
+ kernel.execute();
+
+ EXPECT_THAT(extractTensorData<TypeParam>(output_tensor),
+ ::testing::ElementsAreArray(output_data));
+ EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
+}
+
+} // namespace
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/Slice.cpp b/compiler/luci-interpreter/src/kernels/Slice.cpp
new file mode 100644
index 000000000..c4bc3c57c
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/Slice.cpp
@@ -0,0 +1,149 @@
+/*
+ * 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/Slice.h"
+#include "Utils.h"
+#include <tensorflow/lite/kernels/internal/optimized/optimized_ops.h>
+
+#include <cassert>
+#include <cstring>
+
+namespace luci_interpreter
+{
+
+namespace kernels
+{
+const int max_dim = 4;
+
+Slice::Slice(const Tensor *input, const Tensor *begin, const Tensor *size, Tensor *output)
+ : Kernel({input, begin, size}, {output})
+{
+}
+
+template <typename T>
+Shape calculateOutputShape(const Tensor *input, const Tensor *begin, const Tensor *size)
+{
+ Shape output_shape = Shape(input->shape().num_dims());
+ for (int idx = 0; idx < input->shape().num_dims(); idx++)
+ {
+ T size_value = getTensorData<T>(size)[idx];
+ if (size_value < 0)
+ {
+ if (size_value != -1)
+ {
+ throw std::runtime_error("Invalid size.");
+ }
+ size_value = input->shape().dim(idx) - getTensorData<T>(begin)[idx];
+ }
+ else
+ {
+ if (input->shape().dim(idx) < getTensorData<T>(begin)[idx] + size_value)
+ {
+ throw std::runtime_error("Invalid begin and size.");
+ }
+ }
+ output_shape.dim(idx) = static_cast<int>(size_value);
+ }
+ return output_shape;
+}
+
+template <typename T>
+void getBeginAndSizeVectors(int dimensions, const Tensor *begin, const Tensor *size,
+ std::vector<int> *begins, std::vector<int> *sizes)
+{
+ for (int idx = dimensions - 1; idx >= 0; --idx)
+ {
+ begins->push_back(getTensorData<T>(begin)[idx]);
+ sizes->push_back(getTensorData<T>(size)[idx]);
+ }
+}
+
+void Slice::configure()
+{
+ assert(input()->element_type() == output()->element_type());
+ assert(begin()->element_type() == DataType::S32 || begin()->element_type() == DataType::S64);
+ assert(size()->element_type() == DataType::S32 || size()->element_type() == DataType::S64);
+ assert(begin()->shape().num_dims() == 1);
+ assert(size()->shape().num_dims() == 1);
+ assert(input()->shape().num_dims() <= max_dim);
+
+ if (begin()->element_type() == DataType::S32)
+ {
+ output()->resize(calculateOutputShape<int32_t>(input(), begin(), size()));
+ }
+ else if (begin()->element_type() == DataType::S64)
+ {
+ output()->resize(calculateOutputShape<int64_t>(input(), begin(), size()));
+ }
+ else
+ {
+ throw std::runtime_error("Unsupported type.");
+ }
+}
+
+void Slice::execute() const
+{
+ std::vector<int> begins;
+ begins.reserve(max_dim);
+ std::vector<int> sizes;
+ sizes.reserve(max_dim);
+ if (begin()->element_type() == DataType::S32)
+ {
+ getBeginAndSizeVectors<int32_t>(input()->shape().num_dims(), begin(), size(), &begins, &sizes);
+ }
+ else if (begin()->element_type() == DataType::S64)
+ {
+ getBeginAndSizeVectors<int64_t>(input()->shape().num_dims(), begin(), size(), &begins, &sizes);
+ }
+ else
+ {
+ throw std::runtime_error("Unsupported begin type.");
+ }
+ for (int i = input()->shape().num_dims(); i < max_dim; ++i)
+ {
+ begins.push_back(0);
+ sizes.push_back(1);
+ }
+
+ assert(begins.size() == 4);
+ assert(sizes.size() == 4);
+ tflite::SliceParams op_params{};
+ op_params.begin_count = 4;
+ op_params.size_count = 4;
+ for (int i = 0; i < 4; i++)
+ {
+ op_params.begin[i] = begins[3 - i];
+ op_params.size[i] = sizes[3 - i];
+ }
+ switch (input()->element_type())
+ {
+ case DataType::FLOAT32:
+ tflite::optimized_ops::Slice(op_params, getTensorShape(input()),
+ getTensorData<float>(input()), getTensorShape(output()),
+ getTensorData<float>(output()));
+ break;
+ case DataType::U8:
+ tflite::optimized_ops::Slice(op_params, getTensorShape(input()),
+ getTensorData<uint8_t>(input()), getTensorShape(output()),
+ getTensorData<uint8_t>(output()));
+ break;
+ default:
+ throw std::runtime_error("Unsupported input type.");
+ }
+}
+
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/Slice.h b/compiler/luci-interpreter/src/kernels/Slice.h
new file mode 100644
index 000000000..23c359608
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/Slice.h
@@ -0,0 +1,44 @@
+/*
+ * 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_SLICE_H
+#define LUCI_INTERPRETER_KERNELS_SLICE_H
+
+#include "core/Kernel.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+
+class Slice : public Kernel
+{
+public:
+ Slice(const Tensor *input, const Tensor *begin, const Tensor *size, Tensor *output);
+
+ const Tensor *input() const { return _inputs[0]; }
+ const Tensor *begin() const { return _inputs[1]; }
+ const Tensor *size() const { return _inputs[2]; }
+ Tensor *output() const { return _outputs[0]; }
+
+ void configure() override;
+ void execute() const override;
+};
+
+} // namespace kernels
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_KERNELS_SLICE_H
diff --git a/compiler/luci-interpreter/src/kernels/Slice.test.cpp b/compiler/luci-interpreter/src/kernels/Slice.test.cpp
new file mode 100644
index 000000000..a360a29cc
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/Slice.test.cpp
@@ -0,0 +1,64 @@
+/*
+ * 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/Slice.h"
+#include "kernels/TestUtils.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+namespace
+{
+
+using namespace testing;
+
+template <typename T> class SliceTest : public ::testing::Test
+{
+};
+
+using DataTypes = ::testing::Types<float, uint8_t>;
+TYPED_TEST_CASE(SliceTest, DataTypes);
+
+TYPED_TEST(SliceTest, SimpleTest)
+{
+ std::vector<TypeParam> input_data{1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6};
+ Shape input_shape{3, 2, 3, 1};
+ std::vector<int32_t> begin_data{1, 0, 0, 0};
+ Shape begin_shape{4};
+ std::vector<int32_t> size_data{2, 1, -1, 1};
+ Shape size_shape{4};
+ std::vector<TypeParam> output_data{3, 3, 3, 5, 5, 5};
+ std::vector<int32_t> output_shape{2, 1, 3, 1};
+
+ Tensor input_tensor = makeInputTensor<getElementType<TypeParam>()>(input_shape, input_data);
+ Tensor begin_tensor = makeInputTensor<DataType::S32>(begin_shape, begin_data);
+ Tensor size_tensor = makeInputTensor<DataType::S32>(size_shape, size_data);
+
+ Tensor output_tensor = makeOutputTensor(getElementType<TypeParam>());
+
+ Slice kernel(&input_tensor, &begin_tensor, &size_tensor, &output_tensor);
+ kernel.configure();
+ kernel.execute();
+
+ EXPECT_THAT(extractTensorData<TypeParam>(output_tensor),
+ ::testing::ElementsAreArray(output_data));
+ EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
+}
+
+} // namespace
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/TransposeConv.test.cpp b/compiler/luci-interpreter/src/kernels/TransposeConv.test.cpp
index 3386d3683..b8c0ac497 100644
--- a/compiler/luci-interpreter/src/kernels/TransposeConv.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/TransposeConv.test.cpp
@@ -68,6 +68,8 @@ TEST(TransposeConvTest, FloatSimple)
/*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,
getElementType<float>());
+
+ SUCCEED();
}
TEST(TransposeConvTest, FloatTwoFiltersTest)
@@ -82,21 +84,18 @@ TEST(TransposeConvTest, FloatTwoFiltersTest)
3352, 3652, 2760},
/*params.padding=*/luci::Padding::SAME, /*stride_height=*/1, /*stride_width=*/1,
getElementType<float>());
-}
-TEST(TransposeConvTest, Uint8Simple)
-{
- // TODO
- // Implement GetDequantizedOutput Function.
- // Create Test for Uint8 Case
-}
-TEST(TransposeConvTest, Uint8FiltersTest)
-{
- // TODO
- // Implement GetDequantizedOutput Function.
- // Create Test for Uint8 Case
+ SUCCEED();
}
+// TODO Uint8Simple
+// Implement GetDequantizedOutput Function.
+// Create Test for Uint8 Case
+
+// TODO Uint8FiltersTest
+// Implement GetDequantizedOutput Function.
+// Create Test for Uint8 Case
+
} // namespace
} // namespace kernels
} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/loader/CMakeLists.txt b/compiler/luci-interpreter/src/loader/CMakeLists.txt
index fb36c4ab0..d99485d06 100644
--- a/compiler/luci-interpreter/src/loader/CMakeLists.txt
+++ b/compiler/luci-interpreter/src/loader/CMakeLists.txt
@@ -1,3 +1,5 @@
+nnas_find_package(GTest REQUIRED)
+
set(SOURCES
GraphLoader.h
GraphLoader.cpp
@@ -13,3 +15,8 @@ target_include_directories(luci_interpreter_loader PUBLIC "${LUCI_INTERPRETER_SO
target_link_libraries(luci_interpreter_loader
PUBLIC luci_lang luci_interpreter_core
PRIVATE luci_interpreter_kernels nncc_common)
+
+set(TEST_SOURCES KernelBuilder.test.cpp)
+
+GTest_AddTest(luci_interpreter_loader_test ${TEST_SOURCES})
+target_link_libraries(luci_interpreter_loader_test luci_interpreter_loader)
diff --git a/compiler/luci-interpreter/src/loader/GraphLoader.cpp b/compiler/luci-interpreter/src/loader/GraphLoader.cpp
index 779fa0647..95c654769 100644
--- a/compiler/luci-interpreter/src/loader/GraphLoader.cpp
+++ b/compiler/luci-interpreter/src/loader/GraphLoader.cpp
@@ -16,7 +16,6 @@
#include "loader/GraphLoader.h"
-#include "loader/ModuleLoader.h"
#include "loader/KernelBuilder.h"
#include <loco/IR/Algorithm.h>
@@ -70,9 +69,10 @@ bool isExecutableNode(const luci::CircleNode *node)
switch (node->opcode())
{
// These nodes denote inputs / outputs of a graph.
- case luci::CircleOpcode::CONST:
+ case luci::CircleOpcode::CIRCLECONST:
case luci::CircleOpcode::CIRCLEINPUT:
case luci::CircleOpcode::CIRCLEOUTPUT:
+ case luci::CircleOpcode::CIRCLEOUTPUTEXCLUDE:
// The following nodes denote outputs of multiple-output nodes.
case luci::CircleOpcode::CIRCLEIFOUT:
case luci::CircleOpcode::CIRCLESPLITOUT:
@@ -102,11 +102,12 @@ bool isTensorProducingNode(const luci::CircleNode *node)
} // namespace
-GraphLoader::GraphLoader(const ModuleLoader &module_loader, const loco::Graph *graph,
- RuntimeGraph *runtime_graph, RuntimeToIR &runtime_to_ir,
- std::unordered_map<const loco::Node *, Tensor *> &node_to_tensor)
- : _module_loader(module_loader), _graph(graph), _runtime_graph(runtime_graph),
- _runtime_to_ir(runtime_to_ir), _node_to_tensor(node_to_tensor)
+GraphLoader::GraphLoader(
+ const loco::Graph *graph, RuntimeGraph *runtime_graph, RuntimeToIR &runtime_to_ir,
+ const std::unordered_map<const loco::Graph *, RuntimeGraph *> &graph_to_runtime_graph,
+ std::unordered_map<const loco::Node *, Tensor *> &node_to_tensor)
+ : _graph(graph), _runtime_graph(runtime_graph), _runtime_to_ir(runtime_to_ir),
+ _graph_to_runtime_graph(graph_to_runtime_graph), _node_to_tensor(node_to_tensor)
{
}
@@ -136,6 +137,7 @@ void GraphLoader::loadTensors()
const luci::CircleQuantParam *params = node->quantparam();
quantization.scale.assign(params->scale.cbegin(), params->scale.cend());
quantization.zero_point.assign(params->zerop.cbegin(), params->zerop.cend());
+ quantization.quantized_dimension = params->quantized_dimension;
}
auto tensor = std::make_unique<Tensor>(node->dtype(), std::move(shape), std::move(quantization),
@@ -178,7 +180,7 @@ void GraphLoader::initInputOutputTensors() const
void GraphLoader::loadOperators()
{
- KernelBuilder kernel_builder(_module_loader, *this);
+ KernelBuilder kernel_builder(_graph_to_runtime_graph, _node_to_tensor);
// Create kernels for executable nodes. This has to be done in execution order.
for (const loco::Node *loco_node :
@@ -195,11 +197,4 @@ void GraphLoader::loadOperators()
}
}
-void GraphLoader::load()
-{
- loadTensors();
- initInputOutputTensors();
- loadOperators();
-}
-
} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/loader/GraphLoader.h b/compiler/luci-interpreter/src/loader/GraphLoader.h
index e0adc0f6c..89c5bcad7 100644
--- a/compiler/luci-interpreter/src/loader/GraphLoader.h
+++ b/compiler/luci-interpreter/src/loader/GraphLoader.h
@@ -27,29 +27,23 @@
namespace luci_interpreter
{
-class ModuleLoader;
-
class GraphLoader
{
public:
- GraphLoader(const ModuleLoader &module_loader, const loco::Graph *graph,
- RuntimeGraph *runtime_graph, RuntimeToIR &runtime_to_ir,
+ GraphLoader(const loco::Graph *graph, RuntimeGraph *runtime_graph, RuntimeToIR &runtime_to_ir,
+ const std::unordered_map<const loco::Graph *, RuntimeGraph *> &graph_to_runtime_graph,
std::unordered_map<const loco::Node *, Tensor *> &node_to_tensor);
- void load();
-
- Tensor *getTensorForNode(const loco::Node *node) const { return _node_to_tensor.at(node); }
-
-private:
- void loadOperators();
- void initInputOutputTensors() const;
void loadTensors();
+ void initInputOutputTensors() const;
+ void loadOperators();
- const ModuleLoader &_module_loader;
+private:
const loco::Graph *_graph;
RuntimeGraph *_runtime_graph;
RuntimeToIR &_runtime_to_ir;
+ const std::unordered_map<const loco::Graph *, RuntimeGraph *> &_graph_to_runtime_graph;
std::unordered_map<const loco::Node *, Tensor *> &_node_to_tensor;
};
diff --git a/compiler/luci-interpreter/src/loader/KernelBuilder.cpp b/compiler/luci-interpreter/src/loader/KernelBuilder.cpp
index 56da961dd..12c7f4526 100644
--- a/compiler/luci-interpreter/src/loader/KernelBuilder.cpp
+++ b/compiler/luci-interpreter/src/loader/KernelBuilder.cpp
@@ -21,6 +21,7 @@
#include "kernels/AveragePool2D.h"
#include "kernels/Concatenation.h"
#include "kernels/Conv2D.h"
+#include "kernels/DepthToSpace.h"
#include "kernels/DepthwiseConv2D.h"
#include "kernels/Elu.h"
#include "kernels/FullyConnected.h"
@@ -35,6 +36,8 @@
#include "kernels/Mul.h"
#include "kernels/Pad.h"
#include "kernels/Reshape.h"
+#include "kernels/Reverse.h"
+#include "kernels/Slice.h"
#include "kernels/Softmax.h"
#include "kernels/SpaceToDepth.h"
#include "kernels/Split.h"
@@ -43,8 +46,6 @@
#include "kernels/Unpack.h"
#include "kernels/Transpose.h"
#include "kernels/TransposeConv.h"
-#include "loader/GraphLoader.h"
-#include "loader/ModuleLoader.h"
#include <stdexcept>
@@ -68,20 +69,23 @@ static std::vector<const loco::Node *> collectOutputNodes(const luci::CircleNode
const Tensor *KernelBuilder::getInputTensor(const loco::Node *node) const
{
- const Tensor *tensor = _graph_loader.getTensorForNode(node);
+ const Tensor *tensor = _node_to_tensor.at(node);
assert(tensor != nullptr);
return tensor;
}
const Tensor *KernelBuilder::getOptionalInputTensor(const loco::Node *node) const
{
- // TODO Revise this when optional inputs are implemented in the IR.
+ if (dynamic_cast<const luci::CircleOutputExclude *>(node))
+ {
+ return nullptr;
+ }
return getInputTensor(node);
}
Tensor *KernelBuilder::getOutputTensor(const loco::Node *node) const
{
- Tensor *tensor = _graph_loader.getTensorForNode(node);
+ Tensor *tensor = _node_to_tensor.at(node);
assert(tensor != nullptr);
return tensor;
}
@@ -98,7 +102,7 @@ KernelBuilder::getOutputTensors(const std::vector<const loco::Node *> &nodes) co
RuntimeGraph *KernelBuilder::getRuntimeGraph(const loco::Graph *graph) const
{
- RuntimeGraph *runtime_graph = _module_loader.getRuntimeGraph(graph);
+ RuntimeGraph *runtime_graph = _graph_to_runtime_graph.at(graph);
assert(runtime_graph != nullptr);
return runtime_graph;
}
@@ -120,14 +124,14 @@ std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleAdd *node)
std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleArgMax *node)
{
assert(node->arity() == 2);
- const Tensor *input1 = getInputTensor(node->input());
- const Tensor *input2 = getInputTensor(node->dimension());
+ const Tensor *input = getInputTensor(node->input());
+ const Tensor *axis = getInputTensor(node->dimension());
Tensor *output = getOutputTensor(node);
ArgMaxParams params{};
params.output_type = node->output_type();
- return std::make_unique<kernels::ArgMax>(input1, input2, output, params);
+ return std::make_unique<kernels::ArgMax>(input, axis, output, params);
}
std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleAveragePool2D *node)
@@ -188,6 +192,19 @@ std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleConv2D *node)
return std::make_unique<kernels::Conv2D>(input, filter, bias, output, params);
}
+std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleDepthToSpace *node)
+{
+ assert(node->arity() == 1);
+
+ const Tensor *input = getInputTensor(node->input());
+ Tensor *output = getOutputTensor(node);
+
+ DepthToSpaceParams params{};
+ params.block_size = node->block_size();
+
+ return std::make_unique<kernels::DepthToSpace>(input, output, params);
+}
+
std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleDepthwiseConv2D *node)
{
assert(node->arity() == 3);
@@ -224,14 +241,14 @@ std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleFullyConnected *n
assert(node->arity() == 3);
const Tensor *input = getInputTensor(node->input());
- const Tensor *filter = getInputTensor(node->weights());
+ const Tensor *weights = getInputTensor(node->weights());
const Tensor *bias = getOptionalInputTensor(node->bias());
Tensor *output = getOutputTensor(node);
FullyConnectedParams params{};
params.activation = node->fusedActivationFunction();
- return std::make_unique<kernels::FullyConnected>(input, filter, bias, output, params);
+ return std::make_unique<kernels::FullyConnected>(input, weights, bias, output, params);
}
std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleIf *node)
@@ -255,6 +272,11 @@ std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleIf *node)
else_graph);
}
+std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleInput *)
+{
+ throw std::runtime_error("Input node cannot be executed.");
+}
+
std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleL2Normalize *node)
{
assert(node->arity() == 1);
@@ -323,11 +345,6 @@ std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleLogistic *node)
return std::make_unique<kernels::Logistic>(input, output);
}
-std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleInput *)
-{
- throw std::runtime_error("Input node cannot be executed.");
-}
-
std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleMaxPool2D *node)
{
assert(node->arity() == 1);
@@ -402,6 +419,30 @@ std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleReshape *node)
return std::make_unique<kernels::Reshape>(input, shape, output);
}
+std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleReverseV2 *node)
+{
+ assert(node->arity() == 2);
+
+ const Tensor *input = getInputTensor(node->tensor());
+ const Tensor *axes = getInputTensor(node->axis());
+ Tensor *output = getOutputTensor(node);
+
+ return std::make_unique<kernels::Reverse>(input, axes, output);
+}
+
+std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleSlice *node)
+{
+ assert(node->arity() == 3);
+
+ const Tensor *input = getInputTensor(node->input());
+ const Tensor *begin = getInputTensor(node->begin());
+ const Tensor *size = getInputTensor(node->size());
+
+ Tensor *output = getOutputTensor(node);
+
+ return std::make_unique<kernels::Slice>(input, begin, size, output);
+}
+
std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleSoftmax *node)
{
assert(node->arity() == 1);
@@ -442,6 +483,19 @@ std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleSplit *node)
return std::make_unique<kernels::Split>(axis, input, std::move(outputs));
}
+std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleSqueeze *node)
+{
+ assert(node->arity() == 1);
+
+ const Tensor *input = getInputTensor(node->input());
+ Tensor *output = getOutputTensor(node);
+
+ SqueezeParams params{};
+ params.squeeze_dims = node->squeeze_dims();
+
+ return std::make_unique<kernels::Squeeze>(input, output, params);
+}
+
std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleStridedSlice *node)
{
assert(node->arity() == 4);
@@ -463,21 +517,15 @@ std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleStridedSlice *nod
return std::make_unique<kernels::StridedSlice>(input, begin, end, strides, output, params);
}
-std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleSqueeze *node)
+std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleTranspose *node)
{
- assert(node->arity() == 1);
+ assert(node->arity() == 2);
- const Tensor *input = getInputTensor(node->input());
+ const Tensor *input = getInputTensor(node->a());
+ const Tensor *perm = getInputTensor(node->perm());
Tensor *output = getOutputTensor(node);
- SqueezeParams params{};
- assert(node->squeeze_dims().size() <= 4);
- for (size_t i = 0; i < node->squeeze_dims().size(); i++)
- {
- params.squeeze_dims.push_back(node->squeeze_dims().at(i));
- }
-
- return std::make_unique<kernels::Squeeze>(input, output, params);
+ return std::make_unique<kernels::Transpose>(input, perm, output);
}
std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleTransposeConv *node)
@@ -515,15 +563,4 @@ std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleUnpack *node)
return std::make_unique<kernels::Unpack>(input, std::move(outputs), params);
}
-std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleTranspose *node)
-{
- assert(node->arity() == 2);
-
- const Tensor *input = getInputTensor(node->a());
- const Tensor *perm = getInputTensor(node->perm());
- Tensor *output = getOutputTensor(node);
-
- return std::make_unique<kernels::Transpose>(input, perm, output);
-}
-
} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/loader/KernelBuilder.h b/compiler/luci-interpreter/src/loader/KernelBuilder.h
index 7e30d395b..d5c5a4b56 100644
--- a/compiler/luci-interpreter/src/loader/KernelBuilder.h
+++ b/compiler/luci-interpreter/src/loader/KernelBuilder.h
@@ -24,18 +24,18 @@
#include <memory>
#include <vector>
+#include <unordered_map>
namespace luci_interpreter
{
-class GraphLoader;
-class ModuleLoader;
-
class KernelBuilder : public luci::CircleNodeVisitor<std::unique_ptr<Kernel>>
{
public:
- KernelBuilder(const ModuleLoader &module_loader, const GraphLoader &graph_loader)
- : _module_loader(module_loader), _graph_loader(graph_loader)
+ KernelBuilder(
+ const std::unordered_map<const loco::Graph *, RuntimeGraph *> &graph_to_runtime_graph,
+ const std::unordered_map<const loco::Node *, Tensor *> &node_to_tensor)
+ : _graph_to_runtime_graph(graph_to_runtime_graph), _node_to_tensor(node_to_tensor)
{
}
@@ -45,6 +45,7 @@ public:
std::unique_ptr<Kernel> visit(const luci::CircleConcatenation *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleConv2D *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleConst *node) override;
+ std::unique_ptr<Kernel> visit(const luci::CircleDepthToSpace *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleDepthwiseConv2D *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleElu *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleFullyConnected *node) override;
@@ -61,6 +62,8 @@ public:
std::unique_ptr<Kernel> visit(const luci::CircleOutput *node) override;
std::unique_ptr<Kernel> visit(const luci::CirclePad *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleReshape *node) override;
+ std::unique_ptr<Kernel> visit(const luci::CircleReverseV2 *node) override;
+ std::unique_ptr<Kernel> visit(const luci::CircleSlice *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleSoftmax *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleSpaceToDepth *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleSplit *node) override;
@@ -82,8 +85,8 @@ private:
RuntimeGraph *getRuntimeGraph(const loco::Graph *graph) const;
private:
- const ModuleLoader &_module_loader;
- const GraphLoader &_graph_loader;
+ const std::unordered_map<const loco::Graph *, RuntimeGraph *> &_graph_to_runtime_graph;
+ const std::unordered_map<const loco::Node *, Tensor *> &_node_to_tensor;
};
} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/loader/KernelBuilder.test.cpp b/compiler/luci-interpreter/src/loader/KernelBuilder.test.cpp
new file mode 100644
index 000000000..33bc8ec9b
--- /dev/null
+++ b/compiler/luci-interpreter/src/loader/KernelBuilder.test.cpp
@@ -0,0 +1,743 @@
+/*
+ * 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 "loader/GraphLoader.h"
+#include "loader/KernelBuilder.h"
+
+#include <kernels/Add.h>
+#include <kernels/ArgMax.h>
+#include <kernels/AveragePool2D.h>
+#include <kernels/Concatenation.h>
+#include <kernels/Conv2D.h>
+#include <kernels/DepthToSpace.h>
+#include <kernels/DepthwiseConv2D.h>
+#include <kernels/Elu.h>
+#include <kernels/FullyConnected.h>
+#include <kernels/L2Normalize.h>
+#include <kernels/L2Pool2D.h>
+#include <kernels/LeakyRelu.h>
+#include <kernels/LocalResponseNormalization.h>
+#include <kernels/Logistic.h>
+#include <kernels/MaxPool2D.h>
+#include <kernels/Mean.h>
+#include <kernels/Mul.h>
+#include <kernels/Pad.h>
+#include <kernels/Reshape.h>
+#include <kernels/Reverse.h>
+#include <kernels/Slice.h>
+#include <kernels/Softmax.h>
+#include <kernels/SpaceToDepth.h>
+#include <kernels/Split.h>
+#include <kernels/Squeeze.h>
+#include <kernels/StridedSlice.h>
+#include <kernels/Transpose.h>
+#include <kernels/TransposeConv.h>
+#include <kernels/Unpack.h>
+
+#include <gmock/gmock.h>
+
+namespace luci_interpreter
+{
+namespace
+{
+
+using namespace testing;
+
+class KernelBuilderTest : public Test
+{
+protected:
+ luci::CircleInput *createInputNode() { return createNode<luci::CircleInput>(); }
+
+ 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.
+ // NOTE The type is meaningless for nodes with multiple outputs (corresponding *Out nodes carry
+ // actual output types).
+ node->dtype(loco::DataType::FLOAT32);
+ return node;
+ }
+
+ template <typename NodeOutT> NodeOutT *createNodeOut(loco::Node *node, int index)
+ {
+ auto *node_out = createNode<NodeOutT>();
+ node_out->input(node);
+ node_out->index(index);
+ return node_out;
+ }
+
+ template <typename KernelT> std::unique_ptr<KernelT> buildKernel(const luci::CircleNode *op)
+ {
+ std::unordered_map<const loco::Graph *, RuntimeGraph *> graph_to_runtime_graph;
+
+ RuntimeGraph runtime_graph(nullptr);
+ RuntimeToIR runtime_to_ir;
+ GraphLoader graph_loader(&_graph, &runtime_graph, runtime_to_ir, graph_to_runtime_graph,
+ _node_to_tensor);
+ graph_loader.loadTensors();
+
+ KernelBuilder kernel_builder(graph_to_runtime_graph, _node_to_tensor);
+
+ auto kernel = op->accept(&kernel_builder);
+ return std::unique_ptr<KernelT>(dynamic_cast<KernelT *>(kernel.release()));
+ }
+
+ void checkTensor(const Tensor *tensor, const loco::Node *node)
+ {
+ EXPECT_THAT(tensor, Eq(_node_to_tensor.at(node)));
+ }
+
+private:
+ loco::Graph _graph;
+ std::unordered_map<const loco::Node *, Tensor *> _node_to_tensor;
+};
+
+TEST_F(KernelBuilderTest, Add)
+{
+ auto *input1 = createInputNode();
+ auto *input2 = createInputNode();
+
+ auto *op = createNode<luci::CircleAdd>();
+ op->x(input1);
+ op->y(input2);
+
+ op->fusedActivationFunction(luci::FusedActFunc::RELU);
+
+ auto kernel = buildKernel<kernels::Add>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->input1(), input1);
+ checkTensor(kernel->input2(), input2);
+ checkTensor(kernel->output(), op);
+ EXPECT_THAT(kernel->params().activation, Eq(op->fusedActivationFunction()));
+}
+
+TEST_F(KernelBuilderTest, ArgMax)
+{
+ auto *input = createInputNode();
+ auto *axis = createInputNode();
+
+ auto *op = createNode<luci::CircleArgMax>();
+ op->input(input);
+ op->dimension(axis);
+
+ op->output_type(loco::DataType::FLOAT32);
+
+ auto kernel = buildKernel<kernels::ArgMax>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->input(), input);
+ checkTensor(kernel->axis(), axis);
+ checkTensor(kernel->output(), op);
+ EXPECT_THAT(kernel->params().output_type, Eq(op->output_type()));
+}
+
+TEST_F(KernelBuilderTest, AveragePool2D)
+{
+ auto *input = createInputNode();
+
+ auto *op = createNode<luci::CircleAveragePool2D>();
+ op->value(input);
+
+ op->padding(luci::Padding::SAME);
+ op->filter()->h(11);
+ op->filter()->w(13);
+ op->stride()->h(17);
+ op->stride()->w(19);
+ op->fusedActivationFunction(luci::FusedActFunc::RELU);
+
+ auto kernel = buildKernel<kernels::AveragePool2D>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->input(), input);
+ checkTensor(kernel->output(), op);
+ EXPECT_THAT(kernel->params().padding, Eq(op->padding()));
+ EXPECT_THAT(kernel->params().filter_height, Eq(op->filter()->h()));
+ EXPECT_THAT(kernel->params().filter_width, Eq(op->filter()->w()));
+ EXPECT_THAT(kernel->params().stride_height, Eq(op->stride()->h()));
+ EXPECT_THAT(kernel->params().stride_width, Eq(op->stride()->w()));
+ EXPECT_THAT(kernel->params().activation, Eq(op->fusedActivationFunction()));
+}
+
+TEST_F(KernelBuilderTest, Concatenation)
+{
+ auto *input1 = createInputNode();
+ auto *input2 = createInputNode();
+
+ auto *op = createNode<luci::CircleConcatenation>(2);
+ op->values(0, input1);
+ op->values(1, input2);
+ op->axis(11);
+
+ auto kernel = buildKernel<kernels::Concatenation>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->input(0), input1);
+ checkTensor(kernel->input(1), input2);
+ checkTensor(kernel->output(), op);
+ EXPECT_THAT(kernel->params().axis, Eq(op->axis()));
+}
+
+TEST_F(KernelBuilderTest, Conv2D)
+{
+ auto *input = createInputNode();
+ auto *filter = createInputNode();
+ auto *bias = createInputNode();
+
+ auto *op = createNode<luci::CircleConv2D>();
+ op->input(input);
+ op->filter(filter);
+ op->bias(bias);
+
+ op->padding(luci::Padding::SAME);
+ op->stride()->h(11);
+ op->stride()->w(13);
+ op->dilation()->h(17);
+ op->dilation()->w(19);
+ op->fusedActivationFunction(luci::FusedActFunc::RELU);
+
+ auto kernel = buildKernel<kernels::Conv2D>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->input(), input);
+ checkTensor(kernel->filter(), filter);
+ checkTensor(kernel->bias(), bias);
+ checkTensor(kernel->output(), op);
+ EXPECT_THAT(kernel->params().padding, Eq(op->padding()));
+ EXPECT_THAT(kernel->params().stride_height, Eq(op->stride()->h()));
+ EXPECT_THAT(kernel->params().stride_width, Eq(op->stride()->w()));
+ EXPECT_THAT(kernel->params().dilation_height_factor, Eq(op->dilation()->h()));
+ EXPECT_THAT(kernel->params().dilation_width_factor, Eq(op->dilation()->w()));
+ EXPECT_THAT(kernel->params().activation, Eq(op->fusedActivationFunction()));
+}
+
+TEST_F(KernelBuilderTest, DepthToSpace)
+{
+ auto *input = createInputNode();
+
+ auto *op = createNode<luci::CircleDepthToSpace>();
+ op->input(input);
+
+ op->block_size(11);
+
+ auto kernel = buildKernel<kernels::DepthToSpace>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->input(), input);
+ checkTensor(kernel->output(), op);
+ EXPECT_THAT(kernel->params().block_size, Eq(op->block_size()));
+}
+
+TEST_F(KernelBuilderTest, DepthwiseConv2D)
+{
+ auto *input = createInputNode();
+ auto *filter = createInputNode();
+ auto *bias = createInputNode();
+
+ auto *op = createNode<luci::CircleDepthwiseConv2D>();
+ op->input(input);
+ op->filter(filter);
+ op->bias(bias);
+
+ op->padding(luci::Padding::SAME);
+ op->depthMultiplier(11);
+ op->stride()->h(13);
+ op->stride()->w(17);
+ op->dilation()->h(19);
+ op->dilation()->w(23);
+ op->fusedActivationFunction(luci::FusedActFunc::RELU);
+
+ auto kernel = buildKernel<kernels::DepthwiseConv2D>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->input(), input);
+ checkTensor(kernel->filter(), filter);
+ checkTensor(kernel->bias(), bias);
+ checkTensor(kernel->output(), op);
+ EXPECT_THAT(kernel->params().padding, Eq(op->padding()));
+ EXPECT_THAT(kernel->params().depth_multiplier, Eq(op->depthMultiplier()));
+ EXPECT_THAT(kernel->params().stride_height, Eq(op->stride()->h()));
+ EXPECT_THAT(kernel->params().stride_width, Eq(op->stride()->w()));
+ EXPECT_THAT(kernel->params().dilation_height_factor, Eq(op->dilation()->h()));
+ EXPECT_THAT(kernel->params().dilation_width_factor, Eq(op->dilation()->w()));
+ EXPECT_THAT(kernel->params().activation, Eq(op->fusedActivationFunction()));
+}
+
+TEST_F(KernelBuilderTest, Elu)
+{
+ auto *input = createInputNode();
+
+ auto *op = createNode<luci::CircleElu>();
+ op->features(input);
+
+ auto kernel = buildKernel<kernels::Elu>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->input(), input);
+ checkTensor(kernel->output(), op);
+}
+
+TEST_F(KernelBuilderTest, FullyConnected)
+{
+ auto *input = createInputNode();
+ auto *weights = createInputNode();
+ auto *bias = createInputNode();
+
+ auto *op = createNode<luci::CircleFullyConnected>();
+ op->input(input);
+ op->weights(weights);
+ op->bias(bias);
+
+ op->fusedActivationFunction(luci::FusedActFunc::RELU);
+
+ auto kernel = buildKernel<kernels::FullyConnected>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->input(), input);
+ checkTensor(kernel->weights(), weights);
+ checkTensor(kernel->bias(), bias);
+ checkTensor(kernel->output(), op);
+ EXPECT_THAT(kernel->params().activation, Eq(op->fusedActivationFunction()));
+}
+
+TEST_F(KernelBuilderTest, L2Normalize)
+{
+ auto *input = createInputNode();
+
+ auto *op = createNode<luci::CircleL2Normalize>();
+ op->x(input);
+
+ op->fusedActivationFunction(luci::FusedActFunc::RELU);
+
+ auto kernel = buildKernel<kernels::L2Normalize>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->input(), input);
+ checkTensor(kernel->output(), op);
+ EXPECT_THAT(kernel->params().activation, Eq(op->fusedActivationFunction()));
+}
+
+TEST_F(KernelBuilderTest, L2Pool2D)
+{
+ auto *input = createInputNode();
+
+ auto *op = createNode<luci::CircleL2Pool2D>();
+ op->value(input);
+
+ op->padding(luci::Padding::SAME);
+ op->filter()->h(11);
+ op->filter()->w(13);
+ op->stride()->h(17);
+ op->stride()->w(19);
+ op->fusedActivationFunction(luci::FusedActFunc::RELU);
+
+ auto kernel = buildKernel<kernels::L2Pool2D>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->input(), input);
+ checkTensor(kernel->output(), op);
+ EXPECT_THAT(kernel->params().padding, Eq(op->padding()));
+ EXPECT_THAT(kernel->params().filter_height, Eq(op->filter()->h()));
+ EXPECT_THAT(kernel->params().filter_width, Eq(op->filter()->w()));
+ EXPECT_THAT(kernel->params().stride_height, Eq(op->stride()->h()));
+ EXPECT_THAT(kernel->params().stride_width, Eq(op->stride()->w()));
+ EXPECT_THAT(kernel->params().activation, Eq(op->fusedActivationFunction()));
+}
+
+TEST_F(KernelBuilderTest, LeakyRelu)
+{
+ auto *input = createInputNode();
+
+ auto *op = createNode<luci::CircleLeakyRelu>();
+ op->features(input);
+
+ op->alpha(11.0f);
+
+ auto kernel = buildKernel<kernels::LeakyRelu>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->input(), input);
+ checkTensor(kernel->output(), op);
+ EXPECT_THAT(kernel->params().alpha, Eq(op->alpha()));
+}
+
+TEST_F(KernelBuilderTest, LocalResponseNormalization)
+{
+ auto *input = createInputNode();
+
+ auto *op = createNode<luci::CircleLocalResponseNormalization>();
+ op->input(input);
+
+ op->radius(11);
+ op->bias(13.0f);
+ op->alpha(15.0f);
+ op->beta(17.0f);
+
+ auto kernel = buildKernel<kernels::LocalResponseNormalization>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->input(), input);
+ checkTensor(kernel->output(), op);
+ EXPECT_THAT(kernel->params().radius, Eq(op->radius()));
+ EXPECT_THAT(kernel->params().bias, Eq(op->bias()));
+ EXPECT_THAT(kernel->params().alpha, Eq(op->alpha()));
+ EXPECT_THAT(kernel->params().beta, Eq(op->beta()));
+}
+
+TEST_F(KernelBuilderTest, Logistic)
+{
+ auto *input = createInputNode();
+
+ auto *op = createNode<luci::CircleLogistic>();
+ op->x(input);
+
+ auto kernel = buildKernel<kernels::Logistic>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->input(), input);
+ checkTensor(kernel->output(), op);
+}
+
+TEST_F(KernelBuilderTest, MaxPool2D)
+{
+ auto *input = createInputNode();
+
+ auto *op = createNode<luci::CircleMaxPool2D>();
+ op->value(input);
+
+ op->padding(luci::Padding::SAME);
+ op->filter()->h(11);
+ op->filter()->w(13);
+ op->stride()->h(17);
+ op->stride()->w(19);
+ op->fusedActivationFunction(luci::FusedActFunc::RELU);
+
+ auto kernel = buildKernel<kernels::MaxPool2D>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->input(), input);
+ checkTensor(kernel->output(), op);
+ EXPECT_THAT(kernel->params().padding, Eq(op->padding()));
+ EXPECT_THAT(kernel->params().filter_height, Eq(op->filter()->h()));
+ EXPECT_THAT(kernel->params().filter_width, Eq(op->filter()->w()));
+ EXPECT_THAT(kernel->params().stride_height, Eq(op->stride()->h()));
+ EXPECT_THAT(kernel->params().stride_width, Eq(op->stride()->w()));
+ EXPECT_THAT(kernel->params().activation, Eq(op->fusedActivationFunction()));
+}
+
+TEST_F(KernelBuilderTest, Mean)
+{
+ auto *input = createInputNode();
+ auto *axes = createInputNode();
+
+ auto *op = createNode<luci::CircleMean>();
+ op->input(input);
+ op->reduction_indices(axes);
+
+ op->keep_dims(true);
+
+ auto kernel = buildKernel<kernels::Mean>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->input(), input);
+ checkTensor(kernel->axes(), axes);
+ checkTensor(kernel->output(), op);
+ EXPECT_THAT(kernel->params().keep_dims, Eq(op->keep_dims()));
+}
+
+TEST_F(KernelBuilderTest, Mul)
+{
+ auto *input1 = createInputNode();
+ auto *input2 = createInputNode();
+
+ auto *op = createNode<luci::CircleMul>();
+ op->x(input1);
+ op->y(input2);
+
+ op->fusedActivationFunction(luci::FusedActFunc::RELU);
+
+ auto kernel = buildKernel<kernels::Mul>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->input1(), input1);
+ checkTensor(kernel->input2(), input2);
+ checkTensor(kernel->output(), op);
+ EXPECT_THAT(kernel->params().activation, Eq(op->fusedActivationFunction()));
+}
+
+TEST_F(KernelBuilderTest, Pad)
+{
+ auto *input = createInputNode();
+ auto *paddings = createInputNode();
+
+ auto *op = createNode<luci::CirclePad>();
+ op->input(input);
+ op->paddings(paddings);
+
+ auto kernel = buildKernel<kernels::Pad>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->input(), input);
+ checkTensor(kernel->paddings(), paddings);
+ checkTensor(kernel->output(), op);
+}
+
+TEST_F(KernelBuilderTest, Reshape)
+{
+ auto *input = createInputNode();
+ auto *shape = createInputNode();
+
+ auto *op = createNode<luci::CircleReshape>();
+ op->tensor(input);
+ op->shape(shape);
+
+ auto kernel = buildKernel<kernels::Reshape>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->input(), input);
+ checkTensor(kernel->shape(), shape);
+ checkTensor(kernel->output(), op);
+}
+
+TEST_F(KernelBuilderTest, ReverseV2)
+{
+ auto *input = createInputNode();
+ auto *axes = createInputNode();
+
+ auto *op = createNode<luci::CircleReverseV2>();
+ op->tensor(input);
+ op->axis(axes);
+
+ auto kernel = buildKernel<kernels::Reverse>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->input(), input);
+ checkTensor(kernel->axes(), axes);
+ checkTensor(kernel->output(), op);
+}
+
+TEST_F(KernelBuilderTest, Slice)
+{
+ auto *input = createInputNode();
+ auto *begin = createInputNode();
+ auto *size = createInputNode();
+
+ auto *op = createNode<luci::CircleSlice>();
+ op->input(input);
+ op->begin(begin);
+ op->size(size);
+
+ auto kernel = buildKernel<kernels::Slice>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->input(), input);
+ checkTensor(kernel->begin(), begin);
+ checkTensor(kernel->size(), size);
+ checkTensor(kernel->output(), op);
+}
+
+TEST_F(KernelBuilderTest, Softmax)
+{
+ auto *input = createInputNode();
+
+ auto *op = createNode<luci::CircleSoftmax>();
+ op->logits(input);
+
+ op->beta(11.0f);
+
+ auto kernel = buildKernel<kernels::Softmax>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->input(), input);
+ checkTensor(kernel->output(), op);
+ EXPECT_THAT(kernel->params().beta, Eq(op->beta()));
+}
+
+TEST_F(KernelBuilderTest, SpaceToDepth)
+{
+ auto *input = createInputNode();
+
+ auto *op = createNode<luci::CircleSpaceToDepth>();
+ op->input(input);
+
+ op->block_size(11);
+
+ auto kernel = buildKernel<kernels::SpaceToDepth>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->input(), input);
+ checkTensor(kernel->output(), op);
+ EXPECT_THAT(kernel->params().block_size, op->block_size());
+}
+
+TEST_F(KernelBuilderTest, Split)
+{
+ auto *axis = createInputNode();
+ auto *input = createInputNode();
+ auto *op = createNode<luci::CircleSplit>();
+ auto *output1 = createNodeOut<luci::CircleSplitOut>(op, 0);
+ auto *output2 = createNodeOut<luci::CircleSplitOut>(op, 1);
+
+ op->split_dim(axis);
+ op->input(input);
+
+ op->num_split(2);
+
+ auto kernel = buildKernel<kernels::Split>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->axis(), axis);
+ checkTensor(kernel->input(), input);
+ checkTensor(kernel->output(0), output1);
+ checkTensor(kernel->output(1), output2);
+}
+
+TEST_F(KernelBuilderTest, Squeeze)
+{
+ auto *input = createInputNode();
+
+ auto *op = createNode<luci::CircleSqueeze>();
+ op->input(input);
+
+ op->squeeze_dims({11, 13});
+
+ auto kernel = buildKernel<kernels::Squeeze>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->input(), input);
+ checkTensor(kernel->output(), op);
+ EXPECT_THAT(kernel->params().squeeze_dims, ElementsAreArray(op->squeeze_dims()));
+}
+
+TEST_F(KernelBuilderTest, StridedSlice)
+{
+ auto *input = createInputNode();
+ auto *begin = createInputNode();
+ auto *end = createInputNode();
+ auto *strides = createInputNode();
+
+ auto *op = createNode<luci::CircleStridedSlice>();
+ op->input(input);
+ op->begin(begin);
+ op->end(end);
+ op->strides(strides);
+
+ op->begin_mask(11);
+ op->ellipsis_mask(13);
+ op->end_mask(17);
+ op->new_axis_mask(19);
+ op->shrink_axis_mask(23);
+
+ auto kernel = buildKernel<kernels::StridedSlice>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->input(), input);
+ checkTensor(kernel->begin(), begin);
+ checkTensor(kernel->end(), end);
+ checkTensor(kernel->strides(), strides);
+ checkTensor(kernel->output(), op);
+ EXPECT_THAT(kernel->params().begin_mask, Eq(op->begin_mask()));
+ EXPECT_THAT(kernel->params().ellipsis_mask, Eq(op->ellipsis_mask()));
+ EXPECT_THAT(kernel->params().end_mask, Eq(op->end_mask()));
+ EXPECT_THAT(kernel->params().new_axis_mask, Eq(op->new_axis_mask()));
+ EXPECT_THAT(kernel->params().shrink_axis_mask, Eq(op->shrink_axis_mask()));
+}
+
+TEST_F(KernelBuilderTest, Transpose)
+{
+ auto *input = createInputNode();
+ auto *perm = createInputNode();
+
+ auto *op = createNode<luci::CircleTranspose>();
+ op->a(input);
+ op->perm(perm);
+
+ auto kernel = buildKernel<kernels::Transpose>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->input(), input);
+ checkTensor(kernel->perm(), perm);
+ checkTensor(kernel->output(), op);
+}
+
+TEST_F(KernelBuilderTest, TransposeConv)
+{
+ auto *output_shape = createInputNode();
+ auto *filter = createInputNode();
+ auto *input = createInputNode();
+
+ auto *op = createNode<luci::CircleTransposeConv>();
+ op->inputSizes(output_shape);
+ op->filter(filter);
+ op->outBackprop(input);
+
+ op->padding(luci::Padding::SAME);
+ op->stride()->h(11);
+ op->stride()->w(13);
+
+ auto kernel = buildKernel<kernels::TransposeConv>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->output_shape(), output_shape);
+ checkTensor(kernel->filter(), filter);
+ checkTensor(kernel->input(), input);
+ checkTensor(kernel->output(), op);
+ EXPECT_THAT(kernel->params().padding, Eq(op->padding()));
+ EXPECT_THAT(kernel->params().stride_height, Eq(op->stride()->h()));
+ EXPECT_THAT(kernel->params().stride_width, Eq(op->stride()->w()));
+}
+
+TEST_F(KernelBuilderTest, Unpack)
+{
+ auto *input = createInputNode();
+ auto *op = createNode<luci::CircleUnpack>();
+ auto *output1 = createNodeOut<luci::CircleUnpackOut>(op, 0);
+ auto *output2 = createNodeOut<luci::CircleUnpackOut>(op, 1);
+
+ op->value(input);
+
+ op->num(2);
+ op->axis(11);
+
+ auto kernel = buildKernel<kernels::Unpack>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->input(), input);
+ checkTensor(kernel->output(0), output1);
+ checkTensor(kernel->output(1), output2);
+ EXPECT_THAT(kernel->params().axis, Eq(op->axis()));
+}
+
+TEST_F(KernelBuilderTest, NonExisting1_NEG)
+{
+ auto *op = createNode<luci::CircleConst>();
+ ASSERT_ANY_THROW(buildKernel<Kernel>(op));
+}
+
+TEST_F(KernelBuilderTest, NonExisting2_NEG)
+{
+ auto *op = createNode<luci::CircleInput>();
+ ASSERT_ANY_THROW(buildKernel<Kernel>(op));
+}
+
+TEST_F(KernelBuilderTest, NonExisting3_NEG)
+{
+ auto *op = createNode<luci::CircleOutput>();
+ ASSERT_ANY_THROW(buildKernel<Kernel>(op));
+}
+
+} // namespace
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/loader/ModuleLoader.cpp b/compiler/luci-interpreter/src/loader/ModuleLoader.cpp
index 7780a61b6..b9a2ae0a9 100644
--- a/compiler/luci-interpreter/src/loader/ModuleLoader.cpp
+++ b/compiler/luci-interpreter/src/loader/ModuleLoader.cpp
@@ -41,8 +41,11 @@ void ModuleLoader::load()
{
const loco::Graph *graph = _module->graph(i);
RuntimeGraph *runtime_graph = _graph_to_runtime_graph.at(graph);
- GraphLoader loader(*this, graph, runtime_graph, _runtime_to_ir, _node_to_tensor);
- loader.load();
+ GraphLoader loader(graph, runtime_graph, _runtime_to_ir, _graph_to_runtime_graph,
+ _node_to_tensor);
+ loader.loadTensors();
+ loader.initInputOutputTensors();
+ loader.loadOperators();
}
}
diff --git a/compiler/luci-interpreter/src/loader/ModuleLoader.h b/compiler/luci-interpreter/src/loader/ModuleLoader.h
index 954dbfb61..1af0ed747 100644
--- a/compiler/luci-interpreter/src/loader/ModuleLoader.h
+++ b/compiler/luci-interpreter/src/loader/ModuleLoader.h
@@ -36,11 +36,6 @@ public:
void load();
- RuntimeGraph *getRuntimeGraph(const loco::Graph *graph) const
- {
- return _graph_to_runtime_graph.at(graph);
- }
-
private:
const luci::Module *_module;
RuntimeModule *_runtime_module;
diff --git a/compiler/luci-value-test/CMakeLists.txt b/compiler/luci-value-test/CMakeLists.txt
index 3a5c42b11..ec7463409 100644
--- a/compiler/luci-value-test/CMakeLists.txt
+++ b/compiler/luci-value-test/CMakeLists.txt
@@ -20,6 +20,6 @@ add_test(NAME luci_value_test
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/evalverify.sh"
"${CMAKE_CURRENT_BINARY_DIR}"
"${ARTIFACTS_BIN_PATH}"
- "${NNCC_OVERLAY_DIR}/venv_1_13_2"
+ "${NNCC_OVERLAY_DIR}/venv_2_3_0"
${LUCI_VALUE_TESTS}
)
diff --git a/compiler/luci-value-test/evalverify.sh b/compiler/luci-value-test/evalverify.sh
index dfd55a691..12c9a459a 100755
--- a/compiler/luci-value-test/evalverify.sh
+++ b/compiler/luci-value-test/evalverify.sh
@@ -4,8 +4,10 @@
#
# HOW TO USE
#
-# ./evalverify.sh <path/to/work_dir> <TEST 1> <TEST 2> ...
-# work_dir : build directory of luci-value-test (ex: build/compiler/luci-value-test)
+# ./evalverify.sh <path/to/bin_dir> <path/to/work_dir> <path/to/venv_dir> <TEST 1> <TEST 2> ...
+# bin_dir : build directory of luci-value-test (ex: build/compiler/luci-value-test)
+# work_dir : artifacts directoy where test materials exist
+# venv_dir : python virtual environment home directory
VERIFY_SOURCE_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
VERIFY_SCRIPT_PATH="${VERIFY_SOURCE_PATH}/luci_eval_verifier.py"
diff --git a/compiler/luci-value-test/luci_eval_verifier.py b/compiler/luci-value-test/luci_eval_verifier.py
index 6999110b6..7a2cebb91 100755
--- a/compiler/luci-value-test/luci_eval_verifier.py
+++ b/compiler/luci-value-test/luci_eval_verifier.py
@@ -35,6 +35,10 @@ for i in range(num_inputs):
input_data = np.array(
np.random.randint(0, 256, 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:
raise SystemExit("Unsupported input dtype")
@@ -44,11 +48,6 @@ for i in range(num_inputs):
# Do inference
interpreter.invoke()
-# Get reference output data.
-assert len(interpreter.get_output_details()) == 1 # TODO: Support multiple outputs
-output_details = interpreter.get_output_details()[0]
-ref_output_data = interpreter.get_tensor(output_details["index"])
-
# Execute luci interpreter.
subprocess.run(
[
@@ -56,27 +55,56 @@ subprocess.run(
str(num_inputs), circle_model + ".input", circle_model + ".output"
],
check=True)
-output_data = np.fromfile(circle_model + ".output", output_details["dtype"])
-shape_file = open(circle_model + ".output.shape", 'r')
-output_shape = [int(i) for i in shape_file.read().split(',')]
-shape_file.close()
-luci_output_data = np.reshape(output_data, output_shape)
# Compare the results.
-try:
- if output_details["dtype"] == np.uint8:
- if np.allclose(luci_output_data, ref_output_data, rtol=0, atol=0) == False:
- raise SystemExit("Execution result of " + tflite_model +
- " does not match with " + circle_model)
- elif output_details["dtype"] == np.float32:
- if np.allclose(
- luci_output_data, ref_output_data, rtol=1.e-5, atol=1.e-5) == False:
- raise SystemExit("Execution result of " + tflite_model +
- " does not match with " + circle_model)
- else:
- raise SystemExit("Unsupported data type: ", output_details["dtype"])
-except:
- print(traceback.format_exc())
- quit(255)
+for idx in range(len(interpreter.get_output_details())):
+ output_details = interpreter.get_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)
+ try:
+ if output_details["dtype"] == np.uint8:
+ if np.allclose(
+ luci_output_data,
+ interpreter.get_tensor(
+ interpreter.get_output_details()[idx]["index"]),
+ rtol=0,
+ atol=0) == False:
+ raise SystemExit("Execution result of " + tflite_model +
+ " does not match with " + circle_model)
+ elif output_details["dtype"] == np.float32:
+ if np.allclose(
+ luci_output_data,
+ interpreter.get_tensor(
+ interpreter.get_output_details()[idx]["index"]),
+ rtol=1.e-5,
+ atol=1.e-5) == False:
+ raise SystemExit("Execution result of " + tflite_model +
+ " does not match with " + circle_model)
+ elif output_details["dtype"] == np.int64:
+ if np.allclose(
+ luci_output_data,
+ interpreter.get_tensor(
+ interpreter.get_output_details()[idx]["index"]),
+ rtol=0,
+ atol=0) == False:
+ raise SystemExit("Execution result of " + tflite_model +
+ " does not match with " + circle_model)
+ elif output_details["dtype"] == np.int32:
+ if np.allclose(
+ luci_output_data,
+ interpreter.get_tensor(
+ interpreter.get_output_details()[idx]["index"]),
+ rtol=0,
+ atol=0) == False:
+ raise SystemExit("Execution result of " + tflite_model +
+ " does not match with " + circle_model)
+ else:
+ raise SystemExit("Unsupported data type: ", output_details["dtype"])
+ except:
+ print(traceback.format_exc())
+ quit(255)
quit(0)
diff --git a/compiler/luci-value-test/test.lst b/compiler/luci-value-test/test.lst
index 6a332f92c..0e5231eca 100644
--- a/compiler/luci-value-test/test.lst
+++ b/compiler/luci-value-test/test.lst
@@ -1,81 +1,183 @@
#addeval(Abs_000)
addeval(Add_000)
+#addeval(Add_001)
addeval(Add_U8_000)
-#addeval(ArgMax_000)
-#addeval(ArgMax_001)
-#addeval(ArgMax_002)
-#addeval(ArgMax_003)
-#addeval(ArgMax_U8_000)
-#addeval(ArgMax_U8_001)
-#addeval(ArgMax_U8_002)
-#addeval(ArgMax_U8_003)
+#addeval(AddN_000)
+addeval(ArgMax_000)
+addeval(ArgMax_001)
+addeval(ArgMax_002)
+addeval(ArgMax_003)
+addeval(ArgMax_U8_000)
+addeval(ArgMax_U8_001)
+addeval(ArgMax_U8_002)
+addeval(ArgMax_U8_003)
+#addeval(ArgMin_000)
+#addeval(ArgMin_001)
+#addeval(ArgMin_002)
+#addeval(ArgMin_003)
+#addeval(ArgMin_U8_000)
+#addeval(ArgMin_U8_001)
+#addeval(ArgMin_U8_002)
+#addeval(ArgMin_U8_003)
addeval(AveragePool2D_000)
+#addeval(BatchMatMul_000)
#addeval(BatchMatMulV2_000)
#addeval(BatchMatMulV2_001)
#addeval(BatchToSpaceND_000)
#addeval(Cast_000)
+#addeval(Cast_001)
+#addeval(Ceil_000)
addeval(Concatenation_000)
addeval(Concatenation_U8_000)
addeval(Conv2D_000)
addeval(Conv2D_001)
addeval(Conv2D_002)
+#addeval(Conv2D_003)
addeval(Conv2D_U8_000)
addeval(Conv2D_U8_001)
#addeval(Cos_000)
+#addeval(DepthToSpace_000)
addeval(DepthwiseConv2D_000)
addeval(DepthwiseConv2D_U8_000)
+#addeval(DepthwiseConv2D_U8_001)
+addeval(DepthwiseConv2D_001)
#addeval(Div_000)
+addeval(ELU_000)
#addeval(Equal_000)
#addeval(Exp_000)
+#addeval(ExpandDims_000)
+#addeval(ExpandDims_001)
+#addeval(ExpandDims_002)
+#addeval(ExpandDims_003)
+#addeval(Fill_000)
+#addeval(Fill_001)
+#addeval(Floor_000)
+#addeval(FloorDiv_000)
+#addeval(FloorDiv_001)
+#addeval(FloorMod_000)
+#addeval(FloorMod_001)
addeval(FullyConnected_000)
addeval(FullyConnected_001)
-#addeval(FullyConnected_002)
+addeval(FullyConnected_002)
#addeval(FullyConnected_U8_000)
#addeval(Gather_000)
-#addeval(If_000)
-#addeval(If_001)
+#addeval(GatherNd_000)
+#addeval(Greater_000)
+#addeval(GreaterEqual_000)
+addeval(If_000)
+addeval(If_001)
+addeval(L2Normalize_000)
+addeval(L2Pool2D_000)
+#addeval(L2Pool2D_U8_000)
+addeval(LeakyRelu_000)
+#addeval(Less_000)
+#addeval(LessEqual_000)
+addeval(LocalResponseNormalization_000)
+#addeval(Log_000)
+#addeval(LogicalAnd_000)
#addeval(LogicalNot_000)
#addeval(LogicalOr_000)
-#addeval(Logistic_000)
+addeval(Logistic_000)
+#addeval(LogSoftmax_000)
+#addeval(MatMul_000)
+#addeval(MatrixDiag_000)
+#addeval(MatrixSetDiag_000)
+#addeval(Maximum_000)
addeval(MaxPool2D_000)
addeval(MaxPool2D_U8_000)
addeval(Mean_000)
addeval(Mean_001)
-addeval(Mean_U8_000)
+#addeval(Mean_U8_000)
+#addeval(Minimum_000)
+#addeval(MirrorPad_000)
addeval(Mul_000)
#addeval(Mul_U8_000)
+#addeval(Neg_000)
+#addeval(NotEqual_000)
+#addeval(OneHot_000)
+#addeval(OneHot_001)
+#addeval(OneHot_002)
+#addeval(OneHot_003)
#addeval(Pack_000)
#addeval(Pack_U8_000)
addeval(Pad_000)
addeval(Pad_U8_000)
+#addeval(Pow_000)
+#addeval(PRelu_000)
+#addeval(Range_000)
+#addeval(Rank_000)
+#addeval(ReduceAny_000)
+#addeval(ReduceAny_001)
+#addeval(ReduceAny_002)
+#addeval(ReduceAny_003)
+#addeval(ReduceMax_000)
+#addeval(ReduceMin_000)
#addeval(ReduceProd_000)
#addeval(ReduceProd_001)
#addeval(ReduceProd_002)
#addeval(ReduceProd_003)
#addeval(ReLU_000)
+#addeval(ReLU6_000)
+#addeval(ReLUN1To1_000)
addeval(Reshape_000)
addeval(Reshape_001)
addeval(Reshape_002)
#addeval(Reshape_003)
addeval(Reshape_U8_000)
+#addeval(ResizeBilinear_000)
+#addeval(ResizeNearestNeighbor_000)
+#addeval(ReverseSequence_000)
+#addeval(ReverseV2_000)
+#addeval(Round_000)
#addeval(Rsqrt_000)
+#addeval(ScatterNd_000)
+#addeval(SegmentSum_000)
+#addeval(Select_000)
+#addeval(Select_001)
+#addeval(Select_002)
+#addeval(SelectV2_000)
+#addeval(SelectV2_001)
+#addeval(SelectV2_002)
+#addeval(Shape_000)
#addeval(Sin_000)
+addeval(Slice_000)
addeval(Softmax_000)
#addeval(Softmax_U8_000)
#addeval(SpaceToBatchND_000)
#addeval(SpaceToBatchND_001)
#addeval(SpaceToBatchND_002)
#addeval(SpaceToBatchND_003)
-#addeval(StridedSlice_000)
-#addeval(StridedSlice_001)
+addeval(SpaceToDepth_000)
+#addeval(SparseToDense_000)
+addeval(Split_000)
+#addeval(SplitV_000)
+#addeval(Sqrt_000)
+#addeval(Square_000)
+#addeval(SquaredDifference_000)
+addeval(Squeeze_000)
+addeval(StridedSlice_000)
+addeval(StridedSlice_001)
+addeval(StridedSlice_002)
#addeval(Sub_000)
#addeval(Sub_U8_000)
+#addeval(Sum_000)
+#addeval(Sum_001)
#addeval(Tanh_000)
#addeval(Tile_000)
#addeval(Tile_U8_000)
-#addeval(Transpose_000)
-#addeval(Unpack_000)
-#addeval(Unpack_001)
-#addeval(Unpack_002)
+#addeval(TopKV2_000)
+#addeval(TopKV2_001)
+addeval(Transpose_000)
+#addeval(TransposeConv_000)
+addeval(Unpack_000)
+addeval(Unpack_001)
+addeval(Unpack_002)
+addeval(Unpack_003)
+#addeval(Where_000)
+#addeval(Where_001)
#addeval(While_000)
#addeval(While_001)
+#addeval(While_002)
+#addeval(While_003)
+#addeval(YUV_TO_RGB_U8_000)
+#addeval(ZerosLike_000)
diff --git a/compiler/luci-value-test/tester/src/EvalTester.cpp b/compiler/luci-value-test/tester/src/EvalTester.cpp
index 58f62f54c..09eef223a 100644
--- a/compiler/luci-value-test/tester/src/EvalTester.cpp
+++ b/compiler/luci-value-test/tester/src/EvalTester.cpp
@@ -129,7 +129,7 @@ int entry(int argc, char **argv)
assert(num_inputs == input_nodes.size());
for (int32_t i = 0; i < num_inputs; i++)
{
- const auto *input_node = dynamic_cast<const luci::CircleInput *>(input_nodes[i]);
+ const auto *input_node = loco::must_cast<const luci::CircleInput *>(input_nodes[i]);
std::vector<char> input_data(getTensorSize(input_node));
readDataFromFile(std::string(input_prefix) + std::to_string(i), input_data.data(),
input_data.size());
@@ -141,24 +141,35 @@ int entry(int argc, char **argv)
// Get output.
const auto output_nodes = loco::output_nodes(module->graph());
- // TODO: Support multiple outputs
- assert(output_nodes.size() == 1);
- const auto *output_node = dynamic_cast<const luci::CircleOutput *>(output_nodes[0]);
- std::vector<char> output_data(getTensorSize(output_node));
- interpreter.readOutputTensor(output_node, output_data.data(), output_data.size());
-
- // Output data is written in ${output_file}
- // (ex: Add.circle.output)
- // Output shape is written in ${output_file}.shape
- // (ex: Add.circle.output.shape)
- // TODO: Use HDF5 file format
- writeDataToFile(output_file, output_data.data(), output_data.size());
- auto shape_str = std::to_string(output_node->dim(0).value());
- for (int i = 1; i < output_node->rank(); i++)
+ for (int i = 0; i < module->graph()->outputs()->size(); i++)
{
- shape_str += ",";
- shape_str += std::to_string(output_node->dim(i).value());
+ const auto *output_node = loco::must_cast<const luci::CircleOutput *>(output_nodes[i]);
+ std::vector<char> output_data(getTensorSize(output_node));
+ interpreter.readOutputTensor(output_node, output_data.data(), output_data.size());
+
+ // Output data is written in ${output_file}
+ // (ex: Add.circle.output0)
+ // Output shape is written in ${output_file}.shape
+ // (ex: Add.circle.output0.shape)
+ writeDataToFile(std::string(output_file) + std::to_string(i), output_data.data(),
+ output_data.size());
+ // In case of Tensor output is Scalar value.
+ // The output tensor with rank 0 is treated as a scalar with shape (1)
+ if (output_node->rank() == 0)
+ {
+ writeDataToFile(std::string(output_file) + std::to_string(i) + ".shape", "1", 1);
+ }
+ else
+ {
+ auto shape_str = std::to_string(output_node->dim(0).value());
+ for (int j = 1; j < output_node->rank(); j++)
+ {
+ shape_str += ",";
+ shape_str += std::to_string(output_node->dim(j).value());
+ }
+ writeDataToFile(std::string(output_file) + std::to_string(i) + ".shape", shape_str.c_str(),
+ shape_str.size());
+ }
}
- writeDataToFile(std::string(output_file) + ".shape", shape_str.c_str(), shape_str.size());
return EXIT_SUCCESS;
}
diff --git a/compiler/luci/export/src/CircleOperationExporter.cpp b/compiler/luci/export/src/CircleOperationExporter.cpp
index 3c01b676f..bca122050 100644
--- a/compiler/luci/export/src/CircleOperationExporter.cpp
+++ b/compiler/luci/export/src/CircleOperationExporter.cpp
@@ -102,6 +102,7 @@ public:
void visit(luci::CircleMirrorPad *) final;
void visit(luci::CircleMul *) final;
void visit(luci::CircleNeg *) final;
+ void visit(luci::CircleNonMaxSuppressionV4 *) final;
void visit(luci::CircleNotEqual *) final;
void visit(luci::CircleOneHot *) final;
void visit(luci::CirclePack *) final;
@@ -149,6 +150,7 @@ public:
void visit(luci::CircleTopKV2 *) final;
void visit(luci::CircleTranspose *) final;
void visit(luci::CircleTransposeConv *) final;
+ void visit(luci::CircleUnique *) final;
void visit(luci::CircleUnpack *) final;
void visit(luci::CircleWhere *) final;
void visit(luci::CircleWhile *) final;
@@ -165,9 +167,11 @@ public:
// Virtual for multiple-outputs
void visit(luci::CircleCustomOut *) final {}
void visit(luci::CircleIfOut *) final {}
+ void visit(luci::CircleNonMaxSuppressionV4Out *) final {}
void visit(luci::CircleSplitOut *) final {}
void visit(luci::CircleSplitVOut *) final {}
void visit(luci::CircleTopKV2Out *) final {}
+ void visit(luci::CircleUniqueOut *) final {}
void visit(luci::CircleUnpackOut *) final {}
void visit(luci::CircleWhileOut *) final {}
@@ -599,7 +603,9 @@ void OperationExporter::visit(luci::CircleLocalResponseNormalization *node)
{
export_simple(node, circle::BuiltinOperator_LOCAL_RESPONSE_NORMALIZATION,
circle::BuiltinOptions_LocalResponseNormalizationOptions,
- CreateLocalResponseNormalizationOptions(builder).Union());
+ CreateLocalResponseNormalizationOptions(builder, node->radius(), node->bias(),
+ node->alpha(), node->beta())
+ .Union());
}
void OperationExporter::visit(luci::CircleLog *node)
@@ -691,6 +697,49 @@ void OperationExporter::visit(luci::CircleNeg *node)
CreateNegOptions(builder).Union());
}
+void OperationExporter::visit(luci::CircleNonMaxSuppressionV4 *node)
+{
+ auto nms_outs = loco::succs(node);
+ assert(nms_outs.size() == 2);
+
+ uint32_t op_idx =
+ md.registerBuiltinOpcode(circle::BuiltinOperator_NON_MAX_SUPPRESSION_V4, node->op_version());
+ std::vector<int32_t> inputs_vec{
+ get_tensor_index(node->boxes()), get_tensor_index(node->scores()),
+ get_tensor_index(node->max_output_size()), get_tensor_index(node->iou_threshold()),
+ get_tensor_index(node->score_threshold()),
+ };
+ std::vector<int32_t> outputs_vec;
+
+ for (uint32_t idx = 0; idx < nms_outs.size(); ++idx)
+ {
+ // store in order of index
+ bool found = false;
+ for (auto out : nms_outs)
+ {
+ auto nms_out = loco::must_cast<luci::CircleNonMaxSuppressionV4Out *>(out);
+ if (nms_out->index() == static_cast<int32_t>(idx))
+ {
+ outputs_vec.push_back(get_tensor_index(nms_out));
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ {
+ INTERNAL_EXN("Invalid NonMaxSuppressionV4 output");
+ }
+ }
+
+ auto inputs = builder.CreateVector(inputs_vec);
+ auto outputs = builder.CreateVector(outputs_vec);
+ auto options = CreateNonMaxSuppressionV4Options(builder);
+ auto op_offset =
+ CreateOperator(builder, op_idx, inputs, outputs,
+ circle::BuiltinOptions_NonMaxSuppressionV4Options, options.Union());
+ gd._operators.push_back(op_offset);
+}
+
void OperationExporter::visit(luci::CircleNotEqual *node)
{
export_simple(node, circle::BuiltinOperator_NOT_EQUAL, circle::BuiltinOptions_NotEqualOptions,
@@ -890,7 +939,7 @@ void OperationExporter::visit(luci::CircleSpaceToDepth *node)
{
export_simple(node, circle::BuiltinOperator_SPACE_TO_DEPTH,
circle::BuiltinOptions_SpaceToDepthOptions,
- CreateSpaceToDepthOptions(builder).Union());
+ CreateSpaceToDepthOptions(builder, node->block_size()).Union());
}
void OperationExporter::visit(luci::CircleSparseToDense *node)
@@ -1090,6 +1139,43 @@ void OperationExporter::visit(luci::CircleTransposeConv *node)
.Union());
}
+void OperationExporter::visit(luci::CircleUnique *node)
+{
+ auto unique_outs = loco::succs(node);
+ assert(int32_t(unique_outs.size()) == 2);
+ uint32_t op_idx = md.registerBuiltinOpcode(circle::BuiltinOperator_UNIQUE, node->op_version());
+
+ std::vector<int32_t> inputs_vec{get_tensor_index(node->input())};
+ std::vector<int32_t> outputs_vec;
+
+ for (int32_t index = 0; index < 2; index++)
+ {
+ // store in order of index
+ bool found = false;
+ for (auto out : unique_outs)
+ {
+ auto unique_out = loco::must_cast<luci::CircleUniqueOut *>(out);
+ if (unique_out->index() == index)
+ {
+ outputs_vec.push_back(get_tensor_index(unique_out));
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ {
+ INTERNAL_EXN("Invalid Unique output");
+ }
+ }
+
+ auto inputs = builder.CreateVector(inputs_vec);
+ auto outputs = builder.CreateVector(outputs_vec);
+ auto options = CreateUniqueOptions(builder, to_circle_tensortype(node->idx_out_type()));
+ auto op_offset = CreateOperator(builder, op_idx, inputs, outputs,
+ circle::BuiltinOptions_UniqueOptions, options.Union());
+ gd._operators.push_back(op_offset);
+}
+
void OperationExporter::visit(luci::CircleUnpack *node)
{
LOGGER(l);
diff --git a/compiler/luci/export/src/CircleTensorExporter.cpp b/compiler/luci/export/src/CircleTensorExporter.cpp
index 5cad3920b..dc8c2fbc9 100644
--- a/compiler/luci/export/src/CircleTensorExporter.cpp
+++ b/compiler/luci/export/src/CircleTensorExporter.cpp
@@ -302,7 +302,10 @@ encodeQuantizationParameters(FlatBufferBuilder &builder, luci::CircleQuantParam
scale = builder.CreateVector(quantparam->scale);
zero_point = builder.CreateVector(quantparam->zerop);
}
- return circle::CreateQuantizationParameters(builder, min, max, scale, zero_point);
+ // Note: QuantizationDetails is not supported
+ return circle::CreateQuantizationParameters(builder, min, max, scale, zero_point,
+ circle::QuantizationDetails::QuantizationDetails_NONE,
+ 0, quantparam->quantized_dimension);
}
void exportOpDefinedTensor(const CircleTensoInfo &info, FlatBufferBuilder &builder,
diff --git a/compiler/luci/import/include/luci/Import/Nodes.h b/compiler/luci/import/include/luci/Import/Nodes.h
index 2719a5aec..825c2147d 100644
--- a/compiler/luci/import/include/luci/Import/Nodes.h
+++ b/compiler/luci/import/include/luci/Import/Nodes.h
@@ -73,6 +73,7 @@
#include "Nodes/CircleMirrorPad.h"
#include "Nodes/CircleMul.h"
#include "Nodes/CircleNeg.h"
+#include "Nodes/CircleNonMaxSuppressionV4.h"
#include "Nodes/CircleNotEqual.h"
#include "Nodes/CircleOneHot.h"
#include "Nodes/CirclePack.h"
@@ -120,6 +121,7 @@
#include "Nodes/CircleTopKV2.h"
#include "Nodes/CircleTranspose.h"
#include "Nodes/CircleTransposeConv.h"
+#include "Nodes/CircleUnique.h"
#include "Nodes/CircleUnpack.h"
#include "Nodes/CircleWhere.h"
#include "Nodes/CircleWhile.h"
diff --git a/compiler/luci/import/include/luci/Import/Nodes/CircleNonMaxSuppressionV4.h b/compiler/luci/import/include/luci/Import/Nodes/CircleNonMaxSuppressionV4.h
new file mode 100644
index 000000000..f193aae35
--- /dev/null
+++ b/compiler/luci/import/include/luci/Import/Nodes/CircleNonMaxSuppressionV4.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_IMPORT_OP_CIRCLE_NON_MAX_SUPPRESSION_V4_H__
+#define __LUCI_IMPORT_OP_CIRCLE_NON_MAX_SUPPRESSION_V4_H__
+
+#include "luci/Import/GraphBuilderBase.h"
+
+namespace luci
+{
+
+class CircleNonMaxSuppressionV4GraphBuilder : public GraphBuilderBase
+{
+public:
+ bool validate(const ValidateArgs &args) const final;
+
+ void build(const circle::OperatorT &op, GraphBuilderContext *context) const final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_IMPORT_OP_CIRCLE_NON_MAX_SUPPRESSION_V4_H__
diff --git a/compiler/luci/import/include/luci/Import/Nodes/CircleUnique.h b/compiler/luci/import/include/luci/Import/Nodes/CircleUnique.h
new file mode 100644
index 000000000..ed5b5035d
--- /dev/null
+++ b/compiler/luci/import/include/luci/Import/Nodes/CircleUnique.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_IMPORT_OP_CIRCLE_UNIQUE_H__
+#define __LUCI_IMPORT_OP_CIRCLE_UNIQUE_H__
+
+#include "luci/Import/GraphBuilderBase.h"
+
+namespace luci
+{
+
+class CircleUniqueGraphBuilder : public GraphBuilderBase
+{
+public:
+ bool validate(const ValidateArgs &args) const final;
+
+ void build(const circle::OperatorT &op, GraphBuilderContext *context) const final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_IMPORT_OP_CIRCLE_UNIQUE_H__
diff --git a/compiler/luci/import/src/CircleReader.cpp b/compiler/luci/import/src/CircleReader.cpp
index 81e945dd1..bc7f39762 100644
--- a/compiler/luci/import/src/CircleReader.cpp
+++ b/compiler/luci/import/src/CircleReader.cpp
@@ -156,6 +156,7 @@ luci_quantparam(const circle::QuantizationParametersT *quantization)
const auto &max = quantization->max;
const auto &scale = quantization->scale;
const auto &zero_point = quantization->zero_point;
+ const auto &quantized_dimension = quantization->quantized_dimension;
if ((!min.empty() && !max.empty()) || (!scale.empty() && !zero_point.empty()))
{
@@ -165,6 +166,7 @@ luci_quantparam(const circle::QuantizationParametersT *quantization)
quantparam->max = max;
quantparam->scale = scale;
quantparam->zerop = zero_point;
+ quantparam->quantized_dimension = quantized_dimension;
return quantparam;
}
diff --git a/compiler/luci/import/src/GraphBuilderRegistry.cpp b/compiler/luci/import/src/GraphBuilderRegistry.cpp
index d29557f74..cc328cc16 100644
--- a/compiler/luci/import/src/GraphBuilderRegistry.cpp
+++ b/compiler/luci/import/src/GraphBuilderRegistry.cpp
@@ -82,6 +82,7 @@ GraphBuilderRegistry::GraphBuilderRegistry()
CIRCLE_NODE(MIRROR_PAD, CircleMirrorPadGraphBuilder); // 100
CIRCLE_NODE(MUL, CircleMulGraphBuilder); // 18
CIRCLE_NODE(NEG, CircleNegGraphBuilder); // 59
+ CIRCLE_NODE(NON_MAX_SUPPRESSION_V4, CircleNonMaxSuppressionV4GraphBuilder); // 120,
CIRCLE_NODE(NOT_EQUAL, CircleNotEqualGraphBuilder); // 72
CIRCLE_NODE(ONE_HOT, CircleOneHotGraphBuilder); // 85
CIRCLE_NODE(PACK, CirclePackGraphBuilder); // 83
@@ -129,6 +130,7 @@ GraphBuilderRegistry::GraphBuilderRegistry()
CIRCLE_NODE(TOPK_V2, CircleTopKV2GraphBuilder); // 48
CIRCLE_NODE(TRANSPOSE, CircleTransposeGraphBuilder); // 39
CIRCLE_NODE(TRANSPOSE_CONV, CircleTransposeConvGraphBuilder); // 67
+ CIRCLE_NODE(UNIQUE, CircleUniqueGraphBuilder); // 103
CIRCLE_NODE(UNPACK, CircleUnpackGraphBuilder); // 88
CIRCLE_NODE(WHERE, CircleWhereGraphBuilder); // 109
CIRCLE_NODE(WHILE, CircleWhileGraphBuilder); // 119
@@ -155,10 +157,8 @@ GraphBuilderRegistry::GraphBuilderRegistry()
// BuiltinOperator_ARG_MAX = 56,
// BuiltinOperator_PADV2 = 60,
// BuiltinOperator_FAKE_QUANT = 80,
- // BuiltinOperator_UNIQUE = 103,
// BuiltinOperator_QUANTIZE = 114,
// BuiltinOperator_HARD_SWISH = 117,
- // BuiltinOperator_NON_MAX_SUPPRESSION_V4 = 120,
// BuiltinOperator_NON_MAX_SUPPRESSION_V5 = 121,
// BuiltinOperator_DENSIFY = 124,
}
diff --git a/compiler/luci/import/src/Importer.test.cpp b/compiler/luci/import/src/Importer.test.cpp
index 4426e15fd..8366546f0 100644
--- a/compiler/luci/import/src/Importer.test.cpp
+++ b/compiler/luci/import/src/Importer.test.cpp
@@ -20,4 +20,9 @@
#include <gtest/gtest.h>
-TEST(TensorFlowLiteImport, Dummy) { luci::Importer import; }
+TEST(TensorFlowLiteImport, Dummy)
+{
+ luci::Importer import;
+
+ SUCCEED();
+}
diff --git a/compiler/luci/import/src/Nodes/CircleAbs.cpp b/compiler/luci/import/src/Nodes/CircleAbs.cpp
index 9054986bd..3556dc7fa 100644
--- a/compiler/luci/import/src/Nodes/CircleAbs.cpp
+++ b/compiler/luci/import/src/Nodes/CircleAbs.cpp
@@ -36,7 +36,7 @@ CircleNode *CircleAbsGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleAbs>();
- node->x(inputs[0]);
+ node->x(inputs.at(0));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleAdd.cpp b/compiler/luci/import/src/Nodes/CircleAdd.cpp
index 3b1bb734f..b767d4af2 100644
--- a/compiler/luci/import/src/Nodes/CircleAdd.cpp
+++ b/compiler/luci/import/src/Nodes/CircleAdd.cpp
@@ -36,8 +36,8 @@ CircleNode *CircleAddGraphBuilder::build_node(const circle::OperatorT &op,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleAdd>();
- node->x(inputs[0]);
- node->y(inputs[1]);
+ node->x(inputs.at(0));
+ node->y(inputs.at(1));
const auto *options = op.builtin_options.AsAddOptions();
node->fusedActivationFunction(luci_actfunc(options->fused_activation_function));
diff --git a/compiler/luci/import/src/Nodes/CircleArgMax.cpp b/compiler/luci/import/src/Nodes/CircleArgMax.cpp
index 2679827e2..10e8516f4 100644
--- a/compiler/luci/import/src/Nodes/CircleArgMax.cpp
+++ b/compiler/luci/import/src/Nodes/CircleArgMax.cpp
@@ -36,8 +36,8 @@ CircleNode *CircleArgMaxGraphBuilder::build_node(const circle::OperatorT &op,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleArgMax>();
- node->input(inputs[0]);
- node->dimension(inputs[1]);
+ node->input(inputs.at(0));
+ node->dimension(inputs.at(1));
const auto *options = op.builtin_options.AsArgMaxOptions();
node->output_type(luci_datatype(options->output_type));
diff --git a/compiler/luci/import/src/Nodes/CircleArgMin.cpp b/compiler/luci/import/src/Nodes/CircleArgMin.cpp
index 4d85bbff0..5ff534dbb 100644
--- a/compiler/luci/import/src/Nodes/CircleArgMin.cpp
+++ b/compiler/luci/import/src/Nodes/CircleArgMin.cpp
@@ -36,8 +36,8 @@ CircleNode *CircleArgMinGraphBuilder::build_node(const circle::OperatorT &op,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleArgMin>();
- node->input(inputs[0]);
- node->dimension(inputs[1]);
+ node->input(inputs.at(0));
+ node->dimension(inputs.at(1));
const auto *options = op.builtin_options.AsArgMinOptions();
node->output_type(luci_datatype(options->output_type));
diff --git a/compiler/luci/import/src/Nodes/CircleAveragePool2D.cpp b/compiler/luci/import/src/Nodes/CircleAveragePool2D.cpp
index cfc3cf126..ad011f71f 100644
--- a/compiler/luci/import/src/Nodes/CircleAveragePool2D.cpp
+++ b/compiler/luci/import/src/Nodes/CircleAveragePool2D.cpp
@@ -34,7 +34,7 @@ CircleNode *CircleAveragePool2DGraphBuilder::build_node(const circle::OperatorT
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleAveragePool2D>();
- node->value(inputs[0]);
+ node->value(inputs.at(0));
const auto *options = op.builtin_options.AsPool2DOptions();
node->padding(luci_padding(options->padding));
diff --git a/compiler/luci/import/src/Nodes/CircleBCQFullyConnected.cpp b/compiler/luci/import/src/Nodes/CircleBCQFullyConnected.cpp
index 7cc077ed6..16ecebd5c 100644
--- a/compiler/luci/import/src/Nodes/CircleBCQFullyConnected.cpp
+++ b/compiler/luci/import/src/Nodes/CircleBCQFullyConnected.cpp
@@ -37,11 +37,11 @@ CircleNode *CircleBCQFullyConnectedGraphBuilder::build_node(const circle::Operat
{
auto *node = graph->nodes()->create<CircleBCQFullyConnected>();
- node->input(inputs[0]);
- node->weights_scales(inputs[1]);
- node->weights_binary(inputs[2]);
- node->bias(inputs[3]);
- node->weights_clusters(inputs[4]);
+ node->input(inputs.at(0));
+ node->weights_scales(inputs.at(1));
+ node->weights_binary(inputs.at(2));
+ node->bias(inputs.at(3));
+ node->weights_clusters(inputs.at(4));
// TODO Find and move to appropriate place for setting optional input
if (auto bias = dynamic_cast<luci::CircleOutputExclude *>(node->bias()))
diff --git a/compiler/luci/import/src/Nodes/CircleBCQGather.cpp b/compiler/luci/import/src/Nodes/CircleBCQGather.cpp
index c6d2ab559..464f1ac18 100644
--- a/compiler/luci/import/src/Nodes/CircleBCQGather.cpp
+++ b/compiler/luci/import/src/Nodes/CircleBCQGather.cpp
@@ -37,10 +37,10 @@ CircleNode *CircleBCQGatherGraphBuilder::build_node(const circle::OperatorT &op,
{
auto *node = graph->nodes()->create<CircleBCQGather>();
- node->input_scales(inputs[0]);
- node->input_binary(inputs[1]);
- node->indices(inputs[2]);
- node->input_clusters(inputs[3]);
+ node->input_scales(inputs.at(0));
+ node->input_binary(inputs.at(1));
+ node->indices(inputs.at(2));
+ node->input_clusters(inputs.at(3));
const auto *options = op.builtin_options.AsBCQGatherOptions();
node->input_hidden_size(options->input_hidden_size);
diff --git a/compiler/luci/import/src/Nodes/CircleBatchMatMul.cpp b/compiler/luci/import/src/Nodes/CircleBatchMatMul.cpp
index 6026b2a72..330775691 100644
--- a/compiler/luci/import/src/Nodes/CircleBatchMatMul.cpp
+++ b/compiler/luci/import/src/Nodes/CircleBatchMatMul.cpp
@@ -34,8 +34,8 @@ CircleNode *CircleBatchMatMulGraphBuilder::build_node(const circle::OperatorT &o
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleBatchMatMul>();
- node->x(inputs[0]);
- node->y(inputs[1]);
+ node->x(inputs.at(0));
+ node->y(inputs.at(1));
const auto *options = op.builtin_options.AsBatchMatMulOptions();
node->adj_x(options->adjoint_lhs);
diff --git a/compiler/luci/import/src/Nodes/CircleBatchToSpaceND.cpp b/compiler/luci/import/src/Nodes/CircleBatchToSpaceND.cpp
index 4bbfadf64..8c2039fff 100644
--- a/compiler/luci/import/src/Nodes/CircleBatchToSpaceND.cpp
+++ b/compiler/luci/import/src/Nodes/CircleBatchToSpaceND.cpp
@@ -33,7 +33,7 @@ bool CircleBatchToSpaceNDGraphBuilder::validate(const ValidateArgs &args) const
// input 1 and 2 should have INT32/INT64 type
const auto &tensors = args.reader.tensors();
- const auto &tensor_1 = tensors.at(inputs[1]);
+ const auto &tensor_1 = tensors.at(inputs.at(1));
switch (tensor_1->type)
{
case circle::TensorType_INT32:
@@ -42,7 +42,7 @@ bool CircleBatchToSpaceNDGraphBuilder::validate(const ValidateArgs &args) const
default:
return false;
}
- const auto &tensor_2 = tensors.at(inputs[2]);
+ const auto &tensor_2 = tensors.at(inputs.at(2));
switch (tensor_2->type)
{
case circle::TensorType_INT32:
@@ -53,7 +53,7 @@ bool CircleBatchToSpaceNDGraphBuilder::validate(const ValidateArgs &args) const
}
// Only support input shape dimension 3 and 4 only
- const auto &tensor_0 = tensors.at(inputs[0]);
+ const auto &tensor_0 = tensors.at(inputs.at(0));
const auto t_0_s = tensor_0->shape.size();
if (t_0_s != 3 && t_0_s != 4)
return false;
@@ -68,9 +68,9 @@ CircleNode *CircleBatchToSpaceNDGraphBuilder::build_node(const circle::OperatorT
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleBatchToSpaceND>();
- node->input(inputs[0]);
- node->block_shape(inputs[1]);
- node->crops(inputs[2]);
+ node->input(inputs.at(0));
+ node->block_shape(inputs.at(1));
+ node->crops(inputs.at(2));
// No options for BatchToSpaceND
diff --git a/compiler/luci/import/src/Nodes/CircleCast.cpp b/compiler/luci/import/src/Nodes/CircleCast.cpp
index a4d09b505..7bdb63044 100644
--- a/compiler/luci/import/src/Nodes/CircleCast.cpp
+++ b/compiler/luci/import/src/Nodes/CircleCast.cpp
@@ -47,7 +47,7 @@ bool CircleCastGraphBuilder::validate(const ValidateArgs &args) const
const circle::TensorT &output_tensor = *tensors[outputs[0]];
auto name = tensor_name(output_tensor);
- const auto &tensor_in = tensors.at(inputs[0]);
+ const auto &tensor_in = tensors.at(inputs.at(0));
if (tensor_in->type != options->in_data_type)
{
if (settings->get(luci::UserSettings::Key::DisableValidation))
@@ -77,7 +77,7 @@ CircleNode *CircleCastGraphBuilder::build_node(const circle::OperatorT &op,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleCast>();
- node->x(inputs[0]);
+ node->x(inputs.at(0));
const auto *options = op.builtin_options.AsCastOptions();
if (options != nullptr)
@@ -87,7 +87,7 @@ CircleNode *CircleCastGraphBuilder::build_node(const circle::OperatorT &op,
}
else
{
- node->in_data_type(inputs[0]->dtype());
+ node->in_data_type(inputs.at(0)->dtype());
node->out_data_type(loco::DataType::Unknown);
// type inference should use node->dtype() for Unknown
// export should use BuiltinOptions_NONE for Unknown
diff --git a/compiler/luci/import/src/Nodes/CircleCeil.cpp b/compiler/luci/import/src/Nodes/CircleCeil.cpp
index d3d6cd945..2e1aaa295 100644
--- a/compiler/luci/import/src/Nodes/CircleCeil.cpp
+++ b/compiler/luci/import/src/Nodes/CircleCeil.cpp
@@ -42,7 +42,7 @@ CircleNode *CircleCeilGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleCeil>();
- node->x(inputs[0]);
+ node->x(inputs.at(0));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleConv2D.cpp b/compiler/luci/import/src/Nodes/CircleConv2D.cpp
index 42c5c265a..9516ef16a 100644
--- a/compiler/luci/import/src/Nodes/CircleConv2D.cpp
+++ b/compiler/luci/import/src/Nodes/CircleConv2D.cpp
@@ -39,11 +39,11 @@ CircleNode *CircleConv2DGraphBuilder::build_node(const circle::OperatorT &op,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleConv2D>();
- node->input(inputs[0]);
- node->filter(inputs[1]);
+ node->input(inputs.at(0));
+ node->filter(inputs.at(1));
// For now, bias is required (checked in `verify` method).
assert(inputs.size() == 3);
- node->bias(inputs[2]);
+ node->bias(inputs.at(2));
const auto *options = op.builtin_options.AsConv2DOptions();
node->padding(luci_padding(options->padding));
diff --git a/compiler/luci/import/src/Nodes/CircleCos.cpp b/compiler/luci/import/src/Nodes/CircleCos.cpp
index 5f61cc7f6..27d60c62c 100644
--- a/compiler/luci/import/src/Nodes/CircleCos.cpp
+++ b/compiler/luci/import/src/Nodes/CircleCos.cpp
@@ -36,7 +36,7 @@ CircleNode *CircleCosGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleCos>();
- node->x(inputs[0]);
+ node->x(inputs.at(0));
// No options for Cos
diff --git a/compiler/luci/import/src/Nodes/CircleDepthToSpace.cpp b/compiler/luci/import/src/Nodes/CircleDepthToSpace.cpp
index 827b63468..49d31bb99 100644
--- a/compiler/luci/import/src/Nodes/CircleDepthToSpace.cpp
+++ b/compiler/luci/import/src/Nodes/CircleDepthToSpace.cpp
@@ -40,7 +40,7 @@ bool CircleDepthToSpaceGraphBuilder::validate(const ValidateArgs &args) const
const auto &tensors = args.reader.tensors();
- if (tensors[outputs[0]]->type != tensors[inputs[0]]->type)
+ if (tensors[outputs[0]]->type != tensors[inputs.at(0)]->type)
{
return false;
}
@@ -56,7 +56,7 @@ CircleNode *CircleDepthToSpaceGraphBuilder::build_node(const circle::OperatorT &
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleDepthToSpace>();
- node->input(inputs[0]);
+ node->input(inputs.at(0));
const auto *options = op.builtin_options.AsDepthToSpaceOptions();
node->block_size(options->block_size);
diff --git a/compiler/luci/import/src/Nodes/CircleDepthwiseConv2D.cpp b/compiler/luci/import/src/Nodes/CircleDepthwiseConv2D.cpp
index 2b13f9ebb..53f85f2f5 100644
--- a/compiler/luci/import/src/Nodes/CircleDepthwiseConv2D.cpp
+++ b/compiler/luci/import/src/Nodes/CircleDepthwiseConv2D.cpp
@@ -40,11 +40,11 @@ CircleNode *CircleDepthwiseConv2DGraphBuilder::build_node(const circle::Operator
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleDepthwiseConv2D>();
- node->input(inputs[0]);
- node->filter(inputs[1]);
+ node->input(inputs.at(0));
+ node->filter(inputs.at(1));
if (inputs.size() != 3)
throw oops::UserExn("DepthwiseConv2d without bias is unsupported");
- node->bias(inputs[2]);
+ node->bias(inputs.at(2));
const auto *options = op.builtin_options.AsDepthwiseConv2DOptions();
node->padding(luci_padding(options->padding));
diff --git a/compiler/luci/import/src/Nodes/CircleDiv.cpp b/compiler/luci/import/src/Nodes/CircleDiv.cpp
index d09cfb815..615c224d7 100644
--- a/compiler/luci/import/src/Nodes/CircleDiv.cpp
+++ b/compiler/luci/import/src/Nodes/CircleDiv.cpp
@@ -37,8 +37,8 @@ CircleNode *CircleDivGraphBuilder::build_node(const circle::OperatorT &op,
loco::Graph *graph) const
{
auto node = graph->nodes()->create<CircleDiv>();
- node->x(inputs[0]);
- node->y(inputs[1]);
+ node->x(inputs.at(0));
+ node->y(inputs.at(1));
const auto *options = op.builtin_options.AsDivOptions();
node->fusedActivationFunction(luci_actfunc(options->fused_activation_function));
diff --git a/compiler/luci/import/src/Nodes/CircleElu.cpp b/compiler/luci/import/src/Nodes/CircleElu.cpp
index 37a290cb1..919e95ee4 100644
--- a/compiler/luci/import/src/Nodes/CircleElu.cpp
+++ b/compiler/luci/import/src/Nodes/CircleElu.cpp
@@ -35,7 +35,7 @@ bool CircleEluGraphBuilder::validate(const ValidateArgs &args) const
return false;
const auto &tensors = args.reader.tensors();
- const auto &tensor = tensors.at(inputs[0]);
+ const auto &tensor = tensors.at(inputs.at(0));
switch (tensor->type)
{
@@ -56,7 +56,7 @@ CircleNode *CircleEluGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleElu>();
- node->features(inputs[0]);
+ node->features(inputs.at(0));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleEqual.cpp b/compiler/luci/import/src/Nodes/CircleEqual.cpp
index a53f6e94b..1db33b8ac 100644
--- a/compiler/luci/import/src/Nodes/CircleEqual.cpp
+++ b/compiler/luci/import/src/Nodes/CircleEqual.cpp
@@ -34,7 +34,7 @@ bool CircleEqualGraphBuilder::validate(const ValidateArgs &args) const
const auto &tensors = args.reader.tensors();
- return tensors[inputs[0]]->type == tensors[inputs[1]]->type;
+ return tensors[inputs.at(0)]->type == tensors[inputs.at(1)]->type;
}
CircleNode *CircleEqualGraphBuilder::build_node(const circle::OperatorT &,
@@ -42,8 +42,8 @@ CircleNode *CircleEqualGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleEqual>();
- node->x(inputs[0]);
- node->y(inputs[1]);
+ node->x(inputs.at(0));
+ node->y(inputs.at(1));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleExp.cpp b/compiler/luci/import/src/Nodes/CircleExp.cpp
index a32851458..2c031d6b3 100644
--- a/compiler/luci/import/src/Nodes/CircleExp.cpp
+++ b/compiler/luci/import/src/Nodes/CircleExp.cpp
@@ -31,7 +31,7 @@ bool CircleExpGraphBuilder::validate(const ValidateArgs &args) const
// input type check
const auto &tensors = args.reader.tensors();
- const auto &tensor = tensors.at(inputs[0]);
+ const auto &tensor = tensors.at(inputs.at(0));
switch (tensor->type)
{
case circle::TensorType_FLOAT16:
@@ -51,7 +51,7 @@ CircleNode *CircleExpGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleExp>();
- node->x(inputs[0]);
+ node->x(inputs.at(0));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleExpandDims.cpp b/compiler/luci/import/src/Nodes/CircleExpandDims.cpp
index 1cef67a83..ab537c710 100644
--- a/compiler/luci/import/src/Nodes/CircleExpandDims.cpp
+++ b/compiler/luci/import/src/Nodes/CircleExpandDims.cpp
@@ -34,7 +34,7 @@ bool CircleExpandDimsGraphBuilder::validate(const ValidateArgs &args) const
const auto &tensors = args.reader.tensors();
- return tensors[inputs[1]]->type == circle::TensorType_INT32;
+ return tensors[inputs.at(1)]->type == circle::TensorType_INT32;
}
CircleNode *CircleExpandDimsGraphBuilder::build_node(const circle::OperatorT &,
@@ -42,8 +42,8 @@ CircleNode *CircleExpandDimsGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleExpandDims>();
- node->input(inputs[0]);
- node->axis(inputs[1]);
+ node->input(inputs.at(0));
+ node->axis(inputs.at(1));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleFill.cpp b/compiler/luci/import/src/Nodes/CircleFill.cpp
index 6c3d3a247..95d5b876b 100644
--- a/compiler/luci/import/src/Nodes/CircleFill.cpp
+++ b/compiler/luci/import/src/Nodes/CircleFill.cpp
@@ -37,8 +37,8 @@ CircleNode *CircleFillGraphBuilder::build_node(const circle::OperatorT &op,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleFill>();
- node->dims(inputs[0]);
- node->value(inputs[1]);
+ node->dims(inputs.at(0));
+ node->value(inputs.at(1));
const auto *options = op.builtin_options.AsFillOptions();
(void)options;
diff --git a/compiler/luci/import/src/Nodes/CircleFloor.cpp b/compiler/luci/import/src/Nodes/CircleFloor.cpp
index 302a9eae3..ce756b3b1 100644
--- a/compiler/luci/import/src/Nodes/CircleFloor.cpp
+++ b/compiler/luci/import/src/Nodes/CircleFloor.cpp
@@ -42,7 +42,7 @@ CircleNode *CircleFloorGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleFloor>();
- node->x(inputs[0]);
+ node->x(inputs.at(0));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleFloorDiv.cpp b/compiler/luci/import/src/Nodes/CircleFloorDiv.cpp
index 875197890..55f385d60 100644
--- a/compiler/luci/import/src/Nodes/CircleFloorDiv.cpp
+++ b/compiler/luci/import/src/Nodes/CircleFloorDiv.cpp
@@ -39,8 +39,8 @@ bool CircleFloorDivGraphBuilder::validate(const ValidateArgs &args) const
}
const auto &tensors = args.reader.tensors();
- const auto &tensor_in_0 = tensors.at(inputs[0]);
- const auto &tensor_in_1 = tensors.at(inputs[1]);
+ const auto &tensor_in_0 = tensors.at(inputs.at(0));
+ const auto &tensor_in_1 = tensors.at(inputs.at(1));
const auto &tensor_out = tensors.at(outputs[0]);
if (tensor_in_0->type != tensor_in_1->type)
@@ -59,8 +59,8 @@ CircleNode *CircleFloorDivGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleFloorDiv>();
- node->x(inputs[0]);
- node->y(inputs[1]);
+ node->x(inputs.at(0));
+ node->y(inputs.at(1));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleFloorMod.cpp b/compiler/luci/import/src/Nodes/CircleFloorMod.cpp
index 3ccdce0cd..2101e417e 100644
--- a/compiler/luci/import/src/Nodes/CircleFloorMod.cpp
+++ b/compiler/luci/import/src/Nodes/CircleFloorMod.cpp
@@ -33,8 +33,8 @@ bool CircleFloorModGraphBuilder::validate(const ValidateArgs &args) const
return false;
const auto &tensors = args.reader.tensors();
- const auto &tensor_in_0 = tensors.at(inputs[0]);
- const auto &tensor_in_1 = tensors.at(inputs[1]);
+ const auto &tensor_in_0 = tensors.at(inputs.at(0));
+ const auto &tensor_in_1 = tensors.at(inputs.at(1));
if (tensor_in_0->type != tensor_in_1->type)
return false;
@@ -48,8 +48,8 @@ CircleNode *CircleFloorModGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleFloorMod>();
- node->x(inputs[0]);
- node->y(inputs[1]);
+ node->x(inputs.at(0));
+ node->y(inputs.at(1));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleFullyConnected.cpp b/compiler/luci/import/src/Nodes/CircleFullyConnected.cpp
index 8937e78f1..65a863bde 100644
--- a/compiler/luci/import/src/Nodes/CircleFullyConnected.cpp
+++ b/compiler/luci/import/src/Nodes/CircleFullyConnected.cpp
@@ -38,9 +38,9 @@ CircleNode *CircleFullyConnectedGraphBuilder::build_node(const circle::OperatorT
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleFullyConnected>();
- node->input(inputs[0]);
- node->weights(inputs[1]);
- node->bias(inputs[2]); // bias is optional
+ node->input(inputs.at(0));
+ node->weights(inputs.at(1));
+ node->bias(inputs.at(2)); // bias is optional
// TODO Find and move to appropriate place for setting optional input
if (auto bias = dynamic_cast<luci::CircleOutputExclude *>(node->bias()))
diff --git a/compiler/luci/import/src/Nodes/CircleGather.cpp b/compiler/luci/import/src/Nodes/CircleGather.cpp
index 1caa05ec2..75447a38a 100644
--- a/compiler/luci/import/src/Nodes/CircleGather.cpp
+++ b/compiler/luci/import/src/Nodes/CircleGather.cpp
@@ -56,8 +56,8 @@ CircleNode *CircleGatherGraphBuilder::build_node(const circle::OperatorT &op,
{
auto *node = graph->nodes()->create<CircleGather>();
- node->params(inputs[0]);
- node->indices(inputs[1]);
+ node->params(inputs.at(0));
+ node->indices(inputs.at(1));
const auto *options = op.builtin_options.AsGatherOptions();
node->axis(options->axis);
diff --git a/compiler/luci/import/src/Nodes/CircleGatherNd.cpp b/compiler/luci/import/src/Nodes/CircleGatherNd.cpp
index 621d4ae92..981adbf63 100644
--- a/compiler/luci/import/src/Nodes/CircleGatherNd.cpp
+++ b/compiler/luci/import/src/Nodes/CircleGatherNd.cpp
@@ -36,7 +36,7 @@ bool CircleGatherNdGraphBuilder::validate(const ValidateArgs &args) const
if (outputs.size() != 1)
return false;
- auto &indices_tensor = args.reader.tensors()[inputs[1]];
+ auto &indices_tensor = args.reader.tensors()[inputs.at(1)];
if (!(indices_tensor->type == circle::TensorType::TensorType_INT32 ||
indices_tensor->type == circle::TensorType::TensorType_INT64))
@@ -53,8 +53,8 @@ CircleNode *CircleGatherNdGraphBuilder::build_node(const circle::OperatorT &,
{
auto *node = graph->nodes()->create<CircleGatherNd>();
- node->params(inputs[0]);
- node->indices(inputs[1]);
+ node->params(inputs.at(0));
+ node->indices(inputs.at(1));
// GatherNd options empty
diff --git a/compiler/luci/import/src/Nodes/CircleGreater.cpp b/compiler/luci/import/src/Nodes/CircleGreater.cpp
index 88107589c..1ad0467e4 100644
--- a/compiler/luci/import/src/Nodes/CircleGreater.cpp
+++ b/compiler/luci/import/src/Nodes/CircleGreater.cpp
@@ -43,7 +43,7 @@ bool CircleGreaterGraphBuilder::validate(const ValidateArgs &args) const
const auto &tensors = args.reader.tensors();
- if (tensors[inputs[0]]->type != tensors[inputs[1]]->type)
+ if (tensors[inputs.at(0)]->type != tensors[inputs.at(1)]->type)
return false;
// NOTE: real models do have output dtype NOT BOOL
@@ -67,8 +67,8 @@ CircleNode *CircleGreaterGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleGreater>();
- node->x(inputs[0]);
- node->y(inputs[1]);
+ node->x(inputs.at(0));
+ node->y(inputs.at(1));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleGreaterEqual.cpp b/compiler/luci/import/src/Nodes/CircleGreaterEqual.cpp
index dff1510c5..0ac63b017 100644
--- a/compiler/luci/import/src/Nodes/CircleGreaterEqual.cpp
+++ b/compiler/luci/import/src/Nodes/CircleGreaterEqual.cpp
@@ -40,7 +40,7 @@ bool CircleGreaterEqualGraphBuilder::validate(const ValidateArgs &args) const
const auto &tensors = args.reader.tensors();
- if (tensors[inputs[0]]->type != tensors[inputs[1]]->type)
+ if (tensors[inputs.at(0)]->type != tensors[inputs.at(1)]->type)
{
return false;
}
@@ -53,8 +53,8 @@ CircleNode *CircleGreaterEqualGraphBuilder::build_node(const circle::OperatorT &
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleGreaterEqual>();
- node->x(inputs[0]);
- node->y(inputs[1]);
+ node->x(inputs.at(0));
+ node->y(inputs.at(1));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleIf.cpp b/compiler/luci/import/src/Nodes/CircleIf.cpp
index d6090640d..db9ffe1cd 100644
--- a/compiler/luci/import/src/Nodes/CircleIf.cpp
+++ b/compiler/luci/import/src/Nodes/CircleIf.cpp
@@ -43,7 +43,7 @@ bool CircleIfGraphBuilder::validate(const ValidateArgs &args) const
// input 0 should be BOOL type
const auto &tensors = args.reader.tensors();
- const auto &tensor = tensors.at(inputs[0]);
+ const auto &tensor = tensors.at(inputs.at(0));
if (tensor->type != circle::TensorType_BOOL)
return false;
diff --git a/compiler/luci/import/src/Nodes/CircleInstanceNorm.cpp b/compiler/luci/import/src/Nodes/CircleInstanceNorm.cpp
index b95c54c89..6349fd3b7 100644
--- a/compiler/luci/import/src/Nodes/CircleInstanceNorm.cpp
+++ b/compiler/luci/import/src/Nodes/CircleInstanceNorm.cpp
@@ -38,9 +38,9 @@ CircleNode *CircleInstanceNormGraphBuilder::build_node(const circle::OperatorT &
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleInstanceNorm>();
- node->input(inputs[0]);
- node->gamma(inputs[1]);
- node->beta(inputs[2]);
+ node->input(inputs.at(0));
+ node->gamma(inputs.at(1));
+ node->beta(inputs.at(2));
const auto *options = op.builtin_options.AsInstanceNormOptions();
node->epsilon(options->epsilon);
diff --git a/compiler/luci/import/src/Nodes/CircleL2Normalize.cpp b/compiler/luci/import/src/Nodes/CircleL2Normalize.cpp
index fe10a8572..e4fdc200c 100644
--- a/compiler/luci/import/src/Nodes/CircleL2Normalize.cpp
+++ b/compiler/luci/import/src/Nodes/CircleL2Normalize.cpp
@@ -46,7 +46,7 @@ CircleNode *CircleL2NormalizeGraphBuilder::build_node(const circle::OperatorT &o
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleL2Normalize>();
- node->x(inputs[0]);
+ node->x(inputs.at(0));
const auto *options = op.builtin_options.AsL2NormOptions();
node->fusedActivationFunction(luci_actfunc(options->fused_activation_function));
diff --git a/compiler/luci/import/src/Nodes/CircleL2Pool2D.cpp b/compiler/luci/import/src/Nodes/CircleL2Pool2D.cpp
index 023206695..202d9d6fb 100644
--- a/compiler/luci/import/src/Nodes/CircleL2Pool2D.cpp
+++ b/compiler/luci/import/src/Nodes/CircleL2Pool2D.cpp
@@ -38,7 +38,7 @@ CircleNode *CircleL2Pool2DGraphBuilder::build_node(const circle::OperatorT &op,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleL2Pool2D>();
- node->value(inputs[0]);
+ node->value(inputs.at(0));
const auto *options = op.builtin_options.AsPool2DOptions();
node->padding(luci_padding(options->padding));
diff --git a/compiler/luci/import/src/Nodes/CircleLeakyRelu.cpp b/compiler/luci/import/src/Nodes/CircleLeakyRelu.cpp
index 4957ceae0..ad4979f39 100644
--- a/compiler/luci/import/src/Nodes/CircleLeakyRelu.cpp
+++ b/compiler/luci/import/src/Nodes/CircleLeakyRelu.cpp
@@ -39,7 +39,7 @@ CircleNode *CircleLeakyReluGraphBuilder::build_node(const circle::OperatorT &op,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleLeakyRelu>();
- node->features(inputs[0]);
+ node->features(inputs.at(0));
const auto *options = op.builtin_options.AsLeakyReluOptions();
node->alpha(options->alpha);
diff --git a/compiler/luci/import/src/Nodes/CircleLess.cpp b/compiler/luci/import/src/Nodes/CircleLess.cpp
index 40ad28c6e..506036908 100644
--- a/compiler/luci/import/src/Nodes/CircleLess.cpp
+++ b/compiler/luci/import/src/Nodes/CircleLess.cpp
@@ -39,7 +39,7 @@ bool CircleLessGraphBuilder::validate(const ValidateArgs &args) const
}
const auto &tensors = args.reader.tensors();
- const auto &tensor = tensors.at(inputs[0]);
+ const auto &tensor = tensors.at(inputs.at(0));
switch (tensor->type)
{
@@ -56,7 +56,7 @@ bool CircleLessGraphBuilder::validate(const ValidateArgs &args) const
return false;
}
- if (tensors[inputs[1]]->type != tensor->type)
+ if (tensors[inputs.at(1)]->type != tensor->type)
{
return false;
}
@@ -69,8 +69,8 @@ CircleNode *CircleLessGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleLess>();
- node->x(inputs[0]);
- node->y(inputs[1]);
+ node->x(inputs.at(0));
+ node->y(inputs.at(1));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleLessEqual.cpp b/compiler/luci/import/src/Nodes/CircleLessEqual.cpp
index 13e995069..9b4f934a5 100644
--- a/compiler/luci/import/src/Nodes/CircleLessEqual.cpp
+++ b/compiler/luci/import/src/Nodes/CircleLessEqual.cpp
@@ -40,7 +40,7 @@ bool CircleLessEqualGraphBuilder::validate(const ValidateArgs &args) const
const auto &tensors = args.reader.tensors();
- if (tensors[inputs[0]]->type != tensors[inputs[1]]->type)
+ if (tensors[inputs.at(0)]->type != tensors[inputs.at(1)]->type)
{
return false;
}
@@ -53,8 +53,8 @@ CircleNode *CircleLessEqualGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleLessEqual>();
- node->x(inputs[0]);
- node->y(inputs[1]);
+ node->x(inputs.at(0));
+ node->y(inputs.at(1));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleLocalResponseNormalization.cpp b/compiler/luci/import/src/Nodes/CircleLocalResponseNormalization.cpp
index 7b1f0db56..0e32f62de 100644
--- a/compiler/luci/import/src/Nodes/CircleLocalResponseNormalization.cpp
+++ b/compiler/luci/import/src/Nodes/CircleLocalResponseNormalization.cpp
@@ -37,7 +37,7 @@ CircleNode *CircleLocalResponseNormalizationGraphBuilder::build_node(
const circle::OperatorT &op, const std::vector<CircleNode *> &inputs, loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleLocalResponseNormalization>();
- node->input(inputs[0]);
+ node->input(inputs.at(0));
const auto *options = op.builtin_options.AsLocalResponseNormalizationOptions();
node->radius(options->radius);
diff --git a/compiler/luci/import/src/Nodes/CircleLog.cpp b/compiler/luci/import/src/Nodes/CircleLog.cpp
index 21408327d..346fc43bb 100644
--- a/compiler/luci/import/src/Nodes/CircleLog.cpp
+++ b/compiler/luci/import/src/Nodes/CircleLog.cpp
@@ -35,7 +35,7 @@ bool CircleLogGraphBuilder::validate(const ValidateArgs &args) const
// Must be one of bfloat16, half, float32, float64, complex64, complex128.
// Currently circle supports half(float16), float32, float64, complex64.
const auto &tensors = args.reader.tensors();
- const auto &tensor = tensors.at(inputs[0]);
+ const auto &tensor = tensors.at(inputs.at(0));
switch (tensor->type)
{
case circle::TensorType_FLOAT16:
@@ -55,7 +55,7 @@ CircleNode *CircleLogGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleLog>();
- node->x(inputs[0]);
+ node->x(inputs.at(0));
// No options for Log
diff --git a/compiler/luci/import/src/Nodes/CircleLogSoftmax.cpp b/compiler/luci/import/src/Nodes/CircleLogSoftmax.cpp
index e738c4a0c..ef69e868a 100644
--- a/compiler/luci/import/src/Nodes/CircleLogSoftmax.cpp
+++ b/compiler/luci/import/src/Nodes/CircleLogSoftmax.cpp
@@ -38,7 +38,7 @@ CircleNode *CircleLogSoftmaxGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleLogSoftmax>();
- node->logits(inputs[0]);
+ node->logits(inputs.at(0));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleLogicalAnd.cpp b/compiler/luci/import/src/Nodes/CircleLogicalAnd.cpp
index 8509dbaf3..7844da0f6 100644
--- a/compiler/luci/import/src/Nodes/CircleLogicalAnd.cpp
+++ b/compiler/luci/import/src/Nodes/CircleLogicalAnd.cpp
@@ -46,8 +46,8 @@ CircleNode *CircleLogicalAndGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleLogicalAnd>();
- node->x(inputs[0]);
- node->y(inputs[1]);
+ node->x(inputs.at(0));
+ node->y(inputs.at(1));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleLogicalNot.cpp b/compiler/luci/import/src/Nodes/CircleLogicalNot.cpp
index b1ed3ea37..3758642e4 100644
--- a/compiler/luci/import/src/Nodes/CircleLogicalNot.cpp
+++ b/compiler/luci/import/src/Nodes/CircleLogicalNot.cpp
@@ -31,7 +31,7 @@ bool CircleLogicalNotGraphBuilder::validate(const ValidateArgs &args) const
// Only BOOL type is allowed for the input
const auto &inputs = args.op.inputs;
const auto &tensors = args.reader.tensors();
- const auto &tensor = tensors.at(inputs[0]);
+ const auto &tensor = tensors.at(inputs.at(0));
if (tensor->type != circle::TensorType::TensorType_BOOL)
return false;
@@ -43,7 +43,7 @@ CircleNode *CircleLogicalNotGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleLogicalNot>();
- node->x(inputs[0]);
+ node->x(inputs.at(0));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleLogicalOr.cpp b/compiler/luci/import/src/Nodes/CircleLogicalOr.cpp
index 00eb9c5df..1b87e6f9c 100644
--- a/compiler/luci/import/src/Nodes/CircleLogicalOr.cpp
+++ b/compiler/luci/import/src/Nodes/CircleLogicalOr.cpp
@@ -46,8 +46,8 @@ CircleNode *CircleLogicalOrGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleLogicalOr>();
- node->x(inputs[0]);
- node->y(inputs[1]);
+ node->x(inputs.at(0));
+ node->y(inputs.at(1));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleLogistic.cpp b/compiler/luci/import/src/Nodes/CircleLogistic.cpp
index 85e7e55b2..9606e19cd 100644
--- a/compiler/luci/import/src/Nodes/CircleLogistic.cpp
+++ b/compiler/luci/import/src/Nodes/CircleLogistic.cpp
@@ -32,22 +32,8 @@ bool CircleLogisticGraphBuilder::validate(const ValidateArgs &args) const
if (outputs.size() != 1)
return false;
- // Must be one of the following types
- // float16, float32, float64, complex64, or complex128
const auto &tensors = args.reader.tensors();
- const auto &tensor = tensors.at(inputs[0]);
- switch (tensor->type)
- {
- case circle::TensorType_FLOAT16:
- case circle::TensorType_FLOAT32:
- case circle::TensorType_FLOAT64:
- case circle::TensorType_COMPLEX64:
- break;
- default:
- return false;
- }
-
- if (tensors.at(inputs[0])->type != tensors.at(outputs[0])->type)
+ if (tensors.at(inputs.at(0))->type != tensors.at(outputs[0])->type)
return false;
return true;
@@ -58,7 +44,7 @@ CircleNode *CircleLogisticGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleLogistic>();
- node->x(inputs[0]);
+ node->x(inputs.at(0));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleMatrixDiag.cpp b/compiler/luci/import/src/Nodes/CircleMatrixDiag.cpp
index f4ae03c58..a4a21a8b7 100644
--- a/compiler/luci/import/src/Nodes/CircleMatrixDiag.cpp
+++ b/compiler/luci/import/src/Nodes/CircleMatrixDiag.cpp
@@ -35,7 +35,7 @@ bool CircleMatrixDiagGraphBuilder::validate(const ValidateArgs &args) const
return false;
const auto &tensors = args.reader.tensors();
- const auto &tensor = tensors.at(inputs[0]);
+ const auto &tensor = tensors.at(inputs.at(0));
if (tensors[outputs[0]]->type != tensor->type)
return false;
@@ -48,7 +48,7 @@ CircleNode *CircleMatrixDiagGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleMatrixDiag>();
- node->diagonal(inputs[0]);
+ node->diagonal(inputs.at(0));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleMatrixSetDiag.cpp b/compiler/luci/import/src/Nodes/CircleMatrixSetDiag.cpp
index d6f6aee33..cf0313149 100644
--- a/compiler/luci/import/src/Nodes/CircleMatrixSetDiag.cpp
+++ b/compiler/luci/import/src/Nodes/CircleMatrixSetDiag.cpp
@@ -35,7 +35,7 @@ bool CircleMatrixSetDiagGraphBuilder::validate(const ValidateArgs &args) const
return false;
const auto &tensors = args.reader.tensors();
- const auto &tensor = tensors.at(inputs[0]);
+ const auto &tensor = tensors.at(inputs.at(0));
if (tensors[outputs[0]]->type != tensor->type)
return false;
@@ -48,8 +48,8 @@ CircleNode *CircleMatrixSetDiagGraphBuilder::build_node(const circle::OperatorT
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleMatrixSetDiag>();
- node->input(inputs[0]);
- node->diagonal(inputs[1]);
+ node->input(inputs.at(0));
+ node->diagonal(inputs.at(1));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleMaxPool2D.cpp b/compiler/luci/import/src/Nodes/CircleMaxPool2D.cpp
index 1798819cf..4bca0f40b 100644
--- a/compiler/luci/import/src/Nodes/CircleMaxPool2D.cpp
+++ b/compiler/luci/import/src/Nodes/CircleMaxPool2D.cpp
@@ -36,7 +36,7 @@ CircleNode *CircleMaxPool2DGraphBuilder::build_node(const circle::OperatorT &op,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleMaxPool2D>();
- node->value(inputs[0]);
+ node->value(inputs.at(0));
const auto *options = op.builtin_options.AsPool2DOptions();
node->padding(luci_padding(options->padding));
diff --git a/compiler/luci/import/src/Nodes/CircleMaximum.cpp b/compiler/luci/import/src/Nodes/CircleMaximum.cpp
index 6ca7e4079..4d1468f19 100644
--- a/compiler/luci/import/src/Nodes/CircleMaximum.cpp
+++ b/compiler/luci/import/src/Nodes/CircleMaximum.cpp
@@ -35,7 +35,7 @@ bool CircleMaximumGraphBuilder::validate(const ValidateArgs &args) const
return false;
const auto &tensors = args.reader.tensors();
- const auto &tensor = tensors.at(inputs[0]);
+ const auto &tensor = tensors.at(inputs.at(0));
switch (tensor->type)
{
@@ -49,7 +49,7 @@ bool CircleMaximumGraphBuilder::validate(const ValidateArgs &args) const
return false;
}
- if (tensors[inputs[1]]->type != tensor->type)
+ if (tensors[inputs.at(1)]->type != tensor->type)
return false;
if (tensors[outputs[0]]->type != tensor->type)
@@ -63,8 +63,8 @@ CircleNode *CircleMaximumGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleMaximum>();
- node->x(inputs[0]);
- node->y(inputs[1]);
+ node->x(inputs.at(0));
+ node->y(inputs.at(1));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleMean.cpp b/compiler/luci/import/src/Nodes/CircleMean.cpp
index 8261c7b38..d8fa9a53d 100644
--- a/compiler/luci/import/src/Nodes/CircleMean.cpp
+++ b/compiler/luci/import/src/Nodes/CircleMean.cpp
@@ -34,8 +34,8 @@ CircleNode *CircleMeanGraphBuilder::build_node(const circle::OperatorT &op,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleMean>();
- node->input(inputs[0]);
- node->reduction_indices(inputs[1]);
+ node->input(inputs.at(0));
+ node->reduction_indices(inputs.at(1));
const auto *options = op.builtin_options.AsReducerOptions();
node->keep_dims(options->keep_dims);
diff --git a/compiler/luci/import/src/Nodes/CircleMinimum.cpp b/compiler/luci/import/src/Nodes/CircleMinimum.cpp
index b770f365f..8b4daf197 100644
--- a/compiler/luci/import/src/Nodes/CircleMinimum.cpp
+++ b/compiler/luci/import/src/Nodes/CircleMinimum.cpp
@@ -35,7 +35,7 @@ bool CircleMinimumGraphBuilder::validate(const ValidateArgs &args) const
return false;
const auto &tensors = args.reader.tensors();
- const auto &tensor = tensors.at(inputs[0]);
+ const auto &tensor = tensors.at(inputs.at(0));
switch (tensor->type)
{
@@ -49,7 +49,7 @@ bool CircleMinimumGraphBuilder::validate(const ValidateArgs &args) const
return false;
}
- if (tensors[inputs[1]]->type != tensor->type)
+ if (tensors[inputs.at(1)]->type != tensor->type)
return false;
if (tensors[outputs[0]]->type != tensor->type)
@@ -63,8 +63,8 @@ CircleNode *CircleMinimumGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleMinimum>();
- node->x(inputs[0]);
- node->y(inputs[1]);
+ node->x(inputs.at(0));
+ node->y(inputs.at(1));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleMirrorPad.cpp b/compiler/luci/import/src/Nodes/CircleMirrorPad.cpp
index 41b5e5d80..e0ddd4c11 100644
--- a/compiler/luci/import/src/Nodes/CircleMirrorPad.cpp
+++ b/compiler/luci/import/src/Nodes/CircleMirrorPad.cpp
@@ -38,8 +38,8 @@ CircleNode *CircleMirrorPadGraphBuilder::build_node(const circle::OperatorT &op,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleMirrorPad>();
- node->input(inputs[0]);
- node->paddings(inputs[1]);
+ node->input(inputs.at(0));
+ node->paddings(inputs.at(1));
const auto *options = op.builtin_options.AsMirrorPadOptions();
node->mode(luci_mirrorpad_mode(options->mode));
diff --git a/compiler/luci/import/src/Nodes/CircleMul.cpp b/compiler/luci/import/src/Nodes/CircleMul.cpp
index d4412b96b..e3c4a7ee5 100644
--- a/compiler/luci/import/src/Nodes/CircleMul.cpp
+++ b/compiler/luci/import/src/Nodes/CircleMul.cpp
@@ -37,8 +37,8 @@ CircleNode *CircleMulGraphBuilder::build_node(const circle::OperatorT &op,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleMul>();
- node->x(inputs[0]);
- node->y(inputs[1]);
+ node->x(inputs.at(0));
+ node->y(inputs.at(1));
const auto *options = op.builtin_options.AsMulOptions();
node->fusedActivationFunction(luci_actfunc(options->fused_activation_function));
diff --git a/compiler/luci/import/src/Nodes/CircleNeg.cpp b/compiler/luci/import/src/Nodes/CircleNeg.cpp
index 3d3079ca2..a64a69560 100644
--- a/compiler/luci/import/src/Nodes/CircleNeg.cpp
+++ b/compiler/luci/import/src/Nodes/CircleNeg.cpp
@@ -36,7 +36,7 @@ CircleNode *CircleNegGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleNeg>();
- node->x(inputs[0]);
+ node->x(inputs.at(0));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleNonMaxSuppressionV4.cpp b/compiler/luci/import/src/Nodes/CircleNonMaxSuppressionV4.cpp
new file mode 100644
index 000000000..a4ad4a53d
--- /dev/null
+++ b/compiler/luci/import/src/Nodes/CircleNonMaxSuppressionV4.cpp
@@ -0,0 +1,123 @@
+/*
+ * 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 "luci/Import/Nodes/CircleNonMaxSuppressionV4.h"
+
+#include <luci/IR/Nodes/CircleNonMaxSuppressionV4.h>
+#include <luci/IR/Nodes/CircleNonMaxSuppressionV4Out.h>
+
+#include <loco.h>
+#include <oops/UserExn.h>
+
+namespace luci
+{
+
+bool CircleNonMaxSuppressionV4GraphBuilder::validate(const ValidateArgs &args) const
+{
+ const auto &inputs = args.op.inputs;
+ const auto &outputs = args.op.outputs;
+
+ if (inputs.size() != 5)
+ return false;
+ if (outputs.size() != 2)
+ return false;
+
+ const auto &tensors = args.reader.tensors();
+ const auto &boxes_tensor = tensors.at(inputs[0]);
+ if (boxes_tensor->shape.size() != 2)
+ return false;
+ if (boxes_tensor->shape.at(1) != 4)
+ return false;
+ if (boxes_tensor->shape.at(0) != tensors.at(inputs[1])->shape.at(0))
+ return false;
+
+ if (tensors.at(inputs[2])->type != circle::TensorType_INT32)
+ return false;
+ if (tensors.at(inputs[3])->type != circle::TensorType_FLOAT32)
+ return false;
+ if (tensors.at(inputs[4])->type != circle::TensorType_FLOAT32)
+ return false;
+
+ return true;
+}
+
+/**
+ * @brief NonMaxSuppressionV4 Node builder
+ *
+ * @note Current loco does not provide multiple outputs
+ * We will create multiple NonMasSuppressionV4Oout nodes to emulate this
+ */
+
+void CircleNonMaxSuppressionV4GraphBuilder::build(const circle::OperatorT &op,
+ GraphBuilderContext *context) const
+{
+ assert(context != nullptr);
+
+ auto graph = context->graph();
+
+ const std::vector<int32_t> &inputs = op.inputs;
+ const std::vector<int32_t> &outputs = op.outputs;
+ const auto &tensors = context->reader()->tensors();
+ const auto &opcodes = context->reader()->opcodes();
+ auto tensors_ptr = context->reader()->tensors_ptr();
+ assert(tensors_ptr != nullptr);
+
+ std::vector<CircleNode *> input_nodes;
+ for (const int32_t input_tensor_index : inputs)
+ {
+ input_nodes.push_back(context->nodefinder()->node(input_tensor_index));
+ }
+
+ // Create CircleNonMaxSuppressionV4
+ auto node = graph->nodes()->create<CircleNonMaxSuppressionV4>();
+ node->boxes(input_nodes[0]);
+ node->scores(input_nodes[1]);
+ node->max_output_size(input_nodes[2]);
+ node->iou_threshold(input_nodes[3]);
+ node->score_threshold(input_nodes[4]);
+
+ assert(outputs.size() == 2);
+ {
+ // Let's use name of output 0 as NonMaxSuppressionV4 name
+ const circle::TensorT &output_tensor = *tensors[outputs[0]];
+ node->name(tensor_name(output_tensor));
+ node->op_version(opcodes[op.opcode_index].get()->version);
+
+ // NOTE We don't set quantization for NonMaxSuppressionV4 itself but to virtual outputs
+ }
+
+ // Create virtual outputs of NonMaxSuppressionV4
+ for (size_t n = 0; n < outputs.size(); ++n)
+ {
+ const circle::TensorT &output_tensor = *tensors[outputs[n]];
+
+ auto *nodeout = graph->nodes()->create<CircleNonMaxSuppressionV4Out>();
+ copy_tensor_attributes(output_tensor, nodeout);
+
+ // mark shape_status
+ if (tensors_ptr->Get(outputs[n])->shape() == nullptr)
+ nodeout->shape_status(ShapeStatus::NOSHAPE);
+ else
+ nodeout->shape_status(ShapeStatus::VALID);
+
+ nodeout->input(node);
+ nodeout->index(n);
+
+ context->nodefinder()->enroll(outputs[n], nodeout);
+ }
+}
+
+} // namespace luci
diff --git a/compiler/luci/import/src/Nodes/CircleNotEqual.cpp b/compiler/luci/import/src/Nodes/CircleNotEqual.cpp
index 5b04856db..77e986de1 100644
--- a/compiler/luci/import/src/Nodes/CircleNotEqual.cpp
+++ b/compiler/luci/import/src/Nodes/CircleNotEqual.cpp
@@ -40,7 +40,7 @@ bool CircleNotEqualGraphBuilder::validate(const ValidateArgs &args) const
const auto &tensors = args.reader.tensors();
- if (tensors[inputs[0]]->type != tensors[inputs[1]]->type)
+ if (tensors[inputs.at(0)]->type != tensors[inputs.at(1)]->type)
{
return false;
}
@@ -53,8 +53,8 @@ CircleNode *CircleNotEqualGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleNotEqual>();
- node->x(inputs[0]);
- node->y(inputs[1]);
+ node->x(inputs.at(0));
+ node->y(inputs.at(1));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleOneHot.cpp b/compiler/luci/import/src/Nodes/CircleOneHot.cpp
index 9fdbfa84d..69294e1ed 100644
--- a/compiler/luci/import/src/Nodes/CircleOneHot.cpp
+++ b/compiler/luci/import/src/Nodes/CircleOneHot.cpp
@@ -38,10 +38,10 @@ bool CircleOneHotGraphBuilder::validate(const ValidateArgs &args) const
return false;
const auto &tensors = args.reader.tensors();
- const auto &indices = tensors.at(inputs[0]);
- const auto &depth = tensors.at(inputs[1]);
- const auto &on_value = tensors.at(inputs[2]);
- const auto &off_value = tensors.at(inputs[3]);
+ const auto &indices = tensors.at(inputs.at(0));
+ const auto &depth = tensors.at(inputs.at(1));
+ const auto &on_value = tensors.at(inputs.at(2));
+ const auto &off_value = tensors.at(inputs.at(3));
if (options->axis < -1 || options->axis > static_cast<int32_t>(indices->shape.size()))
return false;
@@ -63,10 +63,10 @@ CircleNode *CircleOneHotGraphBuilder::build_node(const circle::OperatorT &op,
{
auto *node = graph->nodes()->create<CircleOneHot>();
- node->indices(inputs[0]);
- node->depth(inputs[1]);
- node->on_value(inputs[2]);
- node->off_value(inputs[3]);
+ node->indices(inputs.at(0));
+ node->depth(inputs.at(1));
+ node->on_value(inputs.at(2));
+ node->off_value(inputs.at(3));
const auto *options = op.builtin_options.AsOneHotOptions();
node->axis(options->axis);
diff --git a/compiler/luci/import/src/Nodes/CirclePRelu.cpp b/compiler/luci/import/src/Nodes/CirclePRelu.cpp
index 0d87cd423..c07920f7c 100644
--- a/compiler/luci/import/src/Nodes/CirclePRelu.cpp
+++ b/compiler/luci/import/src/Nodes/CirclePRelu.cpp
@@ -39,8 +39,8 @@ CircleNode *CirclePReluGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CirclePRelu>();
- node->input(inputs[0]);
- node->alpha(inputs[1]);
+ node->input(inputs.at(0));
+ node->alpha(inputs.at(1));
// PRelu options are empty
diff --git a/compiler/luci/import/src/Nodes/CirclePad.cpp b/compiler/luci/import/src/Nodes/CirclePad.cpp
index 6abcf2d6c..999173b90 100644
--- a/compiler/luci/import/src/Nodes/CirclePad.cpp
+++ b/compiler/luci/import/src/Nodes/CirclePad.cpp
@@ -38,8 +38,8 @@ CircleNode *CirclePadGraphBuilder::build_node(const circle::OperatorT &op,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CirclePad>();
- node->input(inputs[0]);
- node->paddings(inputs[1]);
+ node->input(inputs.at(0));
+ node->paddings(inputs.at(1));
const auto *options = op.builtin_options.AsPadOptions();
(void)options; // There are no options.
diff --git a/compiler/luci/import/src/Nodes/CirclePow.cpp b/compiler/luci/import/src/Nodes/CirclePow.cpp
index ff9833165..def012614 100644
--- a/compiler/luci/import/src/Nodes/CirclePow.cpp
+++ b/compiler/luci/import/src/Nodes/CirclePow.cpp
@@ -39,8 +39,8 @@ CircleNode *CirclePowGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CirclePow>();
- node->x(inputs[0]);
- node->y(inputs[1]);
+ node->x(inputs.at(0));
+ node->y(inputs.at(1));
// Pow options are empty
diff --git a/compiler/luci/import/src/Nodes/CircleRange.cpp b/compiler/luci/import/src/Nodes/CircleRange.cpp
index c21191605..38dc44ed6 100644
--- a/compiler/luci/import/src/Nodes/CircleRange.cpp
+++ b/compiler/luci/import/src/Nodes/CircleRange.cpp
@@ -36,9 +36,9 @@ CircleNode *CircleRangeGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleRange>();
- node->start(inputs[0]);
- node->limit(inputs[1]);
- node->delta(inputs[2]);
+ node->start(inputs.at(0));
+ node->limit(inputs.at(1));
+ node->delta(inputs.at(2));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleRank.cpp b/compiler/luci/import/src/Nodes/CircleRank.cpp
index 705ae0120..12658b192 100644
--- a/compiler/luci/import/src/Nodes/CircleRank.cpp
+++ b/compiler/luci/import/src/Nodes/CircleRank.cpp
@@ -38,7 +38,7 @@ CircleNode *CircleRankGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleRank>();
- node->input(inputs[0]);
+ node->input(inputs.at(0));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleReduceAny.cpp b/compiler/luci/import/src/Nodes/CircleReduceAny.cpp
index 030c5304c..21a821951 100644
--- a/compiler/luci/import/src/Nodes/CircleReduceAny.cpp
+++ b/compiler/luci/import/src/Nodes/CircleReduceAny.cpp
@@ -31,8 +31,8 @@ bool CircleReduceAnyGraphBuilder::validate(const ValidateArgs &args) const
return false;
const auto &tensors = args.reader.tensors();
- const auto &tensor_0 = tensors.at(inputs[0]);
- const auto &tensor_1 = tensors.at(inputs[1]);
+ const auto &tensor_0 = tensors.at(inputs.at(0));
+ const auto &tensor_1 = tensors.at(inputs.at(1));
const auto &tensor_o = tensors.at(outputs[0]);
if (tensor_0->type != circle::TensorType_BOOL)
@@ -57,8 +57,8 @@ CircleNode *CircleReduceAnyGraphBuilder::build_node(const circle::OperatorT &op,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleReduceAny>();
- node->input(inputs[0]);
- node->reduction_indices(inputs[1]);
+ node->input(inputs.at(0));
+ node->reduction_indices(inputs.at(1));
const auto *options = op.builtin_options.AsReducerOptions();
node->keep_dims(options->keep_dims);
diff --git a/compiler/luci/import/src/Nodes/CircleReduceMax.cpp b/compiler/luci/import/src/Nodes/CircleReduceMax.cpp
index 8ca8e2e34..05492dbc6 100644
--- a/compiler/luci/import/src/Nodes/CircleReduceMax.cpp
+++ b/compiler/luci/import/src/Nodes/CircleReduceMax.cpp
@@ -33,7 +33,7 @@ bool CircleReduceMaxGraphBuilder::validate(const ValidateArgs &args) const
return false;
const auto &tensors = args.reader.tensors();
- const auto &tensor_axis = tensors.at(inputs[1]);
+ const auto &tensor_axis = tensors.at(inputs.at(1));
switch (tensor_axis->type)
{
@@ -52,8 +52,8 @@ CircleNode *CircleReduceMaxGraphBuilder::build_node(const circle::OperatorT &op,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleReduceMax>();
- node->input(inputs[0]);
- node->reduction_indices(inputs[1]);
+ node->input(inputs.at(0));
+ node->reduction_indices(inputs.at(1));
const auto *options = op.builtin_options.AsReducerOptions();
node->keep_dims(options->keep_dims);
diff --git a/compiler/luci/import/src/Nodes/CircleReduceMin.cpp b/compiler/luci/import/src/Nodes/CircleReduceMin.cpp
index 3020c3778..117d5295a 100644
--- a/compiler/luci/import/src/Nodes/CircleReduceMin.cpp
+++ b/compiler/luci/import/src/Nodes/CircleReduceMin.cpp
@@ -33,7 +33,7 @@ bool CircleReduceMinGraphBuilder::validate(const ValidateArgs &args) const
return false;
const auto &tensors = args.reader.tensors();
- const auto &tensor_axis = tensors.at(inputs[1]);
+ const auto &tensor_axis = tensors.at(inputs.at(1));
switch (tensor_axis->type)
{
@@ -52,8 +52,8 @@ CircleNode *CircleReduceMinGraphBuilder::build_node(const circle::OperatorT &op,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleReduceMin>();
- node->input(inputs[0]);
- node->reduction_indices(inputs[1]);
+ node->input(inputs.at(0));
+ node->reduction_indices(inputs.at(1));
const auto *options = op.builtin_options.AsReducerOptions();
node->keep_dims(options->keep_dims);
diff --git a/compiler/luci/import/src/Nodes/CircleReduceProd.cpp b/compiler/luci/import/src/Nodes/CircleReduceProd.cpp
index 2bb43f6ce..5f054586e 100644
--- a/compiler/luci/import/src/Nodes/CircleReduceProd.cpp
+++ b/compiler/luci/import/src/Nodes/CircleReduceProd.cpp
@@ -30,7 +30,7 @@ bool CircleReduceProdGraphBuilder::validate(const ValidateArgs &args) const
return false;
const auto &tensors = args.reader.tensors();
- const auto &tensor_1 = tensors.at(inputs[1]);
+ const auto &tensor_1 = tensors.at(inputs.at(1));
// TODO check input types
@@ -52,8 +52,8 @@ CircleNode *CircleReduceProdGraphBuilder::build_node(const circle::OperatorT &op
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleReduceProd>();
- node->input(inputs[0]);
- node->reduction_indices(inputs[1]);
+ node->input(inputs.at(0));
+ node->reduction_indices(inputs.at(1));
const auto *options = op.builtin_options.AsReducerOptions();
node->keep_dims(options->keep_dims);
diff --git a/compiler/luci/import/src/Nodes/CircleRelu.cpp b/compiler/luci/import/src/Nodes/CircleRelu.cpp
index 056268a5b..8e1c32a3a 100644
--- a/compiler/luci/import/src/Nodes/CircleRelu.cpp
+++ b/compiler/luci/import/src/Nodes/CircleRelu.cpp
@@ -39,7 +39,7 @@ CircleNode *CircleReluGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleRelu>();
- node->features(inputs[0]);
+ node->features(inputs.at(0));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleRelu6.cpp b/compiler/luci/import/src/Nodes/CircleRelu6.cpp
index 5b443993b..0283d7350 100644
--- a/compiler/luci/import/src/Nodes/CircleRelu6.cpp
+++ b/compiler/luci/import/src/Nodes/CircleRelu6.cpp
@@ -39,7 +39,7 @@ CircleNode *CircleRelu6GraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleRelu6>();
- node->features(inputs[0]);
+ node->features(inputs.at(0));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleReluN1To1.cpp b/compiler/luci/import/src/Nodes/CircleReluN1To1.cpp
index edf662fb9..7f517bc0d 100644
--- a/compiler/luci/import/src/Nodes/CircleReluN1To1.cpp
+++ b/compiler/luci/import/src/Nodes/CircleReluN1To1.cpp
@@ -41,7 +41,7 @@ CircleNode *CircleReluN1To1GraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleReluN1To1>();
- node->features(inputs[0]);
+ node->features(inputs.at(0));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleReshape.cpp b/compiler/luci/import/src/Nodes/CircleReshape.cpp
index f72c152b1..996ae9d20 100644
--- a/compiler/luci/import/src/Nodes/CircleReshape.cpp
+++ b/compiler/luci/import/src/Nodes/CircleReshape.cpp
@@ -62,7 +62,7 @@ CircleNode *CircleReshapeGraphBuilder::build_node(const circle::OperatorT &op,
{
// If the second input is not provided, generate it based on the value of the attribute.
// TODO Presence of the second input is the current requirement of the IR.
- auto *shape_node = (inputs.size() == 2) ? inputs[1] : nullptr;
+ auto *shape_node = (inputs.size() == 2) ? inputs.at(1) : nullptr;
if (shape_node == nullptr)
{
const auto *options = op.builtin_options.AsReshapeOptions();
@@ -77,7 +77,7 @@ CircleNode *CircleReshapeGraphBuilder::build_node(const circle::OperatorT &op,
}
auto *node = graph->nodes()->create<CircleReshape>();
- node->tensor(inputs[0]);
+ node->tensor(inputs.at(0));
node->shape(shape_node);
const auto *options = op.builtin_options.AsReshapeOptions();
diff --git a/compiler/luci/import/src/Nodes/CircleResizeBilinear.cpp b/compiler/luci/import/src/Nodes/CircleResizeBilinear.cpp
index 6128f1b86..0fccb7b44 100644
--- a/compiler/luci/import/src/Nodes/CircleResizeBilinear.cpp
+++ b/compiler/luci/import/src/Nodes/CircleResizeBilinear.cpp
@@ -38,8 +38,8 @@ CircleNode *CircleResizeBilinearGraphBuilder::build_node(const circle::OperatorT
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleResizeBilinear>();
- node->input(inputs[0]);
- node->size(inputs[1]);
+ node->input(inputs.at(0));
+ node->size(inputs.at(1));
const auto *options = op.builtin_options.AsResizeBilinearOptions();
node->align_corners(options->align_corners);
diff --git a/compiler/luci/import/src/Nodes/CircleResizeNearestNeighbor.cpp b/compiler/luci/import/src/Nodes/CircleResizeNearestNeighbor.cpp
index a1f1ef0ff..324323f59 100644
--- a/compiler/luci/import/src/Nodes/CircleResizeNearestNeighbor.cpp
+++ b/compiler/luci/import/src/Nodes/CircleResizeNearestNeighbor.cpp
@@ -37,8 +37,8 @@ CircleNode *CircleResizeNearestNeighborGraphBuilder::build_node(
const circle::OperatorT &op, const std::vector<CircleNode *> &inputs, loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleResizeNearestNeighbor>();
- node->input(inputs[0]);
- node->size(inputs[1]);
+ node->input(inputs.at(0));
+ node->size(inputs.at(1));
const auto *options = op.builtin_options.AsResizeNearestNeighborOptions();
node->align_corners(options->align_corners);
diff --git a/compiler/luci/import/src/Nodes/CircleReverseSequence.cpp b/compiler/luci/import/src/Nodes/CircleReverseSequence.cpp
index 72d3b153d..ad11d4c63 100644
--- a/compiler/luci/import/src/Nodes/CircleReverseSequence.cpp
+++ b/compiler/luci/import/src/Nodes/CircleReverseSequence.cpp
@@ -34,8 +34,8 @@ bool CircleReverseSequenceGraphBuilder::validate(const ValidateArgs &args) const
return false;
const auto &tensors = args.reader.tensors();
- const auto &tensor_in = tensors.at(inputs[0]);
- const auto &tensor_lengths = tensors.at(inputs[1]);
+ const auto &tensor_in = tensors.at(inputs.at(0));
+ const auto &tensor_lengths = tensors.at(inputs.at(1));
const auto &tensor_out = tensors.at(outputs[0]);
switch (tensor_lengths->type)
@@ -58,8 +58,8 @@ CircleNode *CircleReverseSequenceGraphBuilder::build_node(const circle::Operator
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleReverseSequence>();
- node->input(inputs[0]);
- node->seq_lengths(inputs[1]);
+ node->input(inputs.at(0));
+ node->seq_lengths(inputs.at(1));
const auto *options = op.builtin_options.AsReverseSequenceOptions();
node->seq_axis(options->seq_dim);
diff --git a/compiler/luci/import/src/Nodes/CircleReverseV2.cpp b/compiler/luci/import/src/Nodes/CircleReverseV2.cpp
index cd18128a7..e2e53bb4b 100644
--- a/compiler/luci/import/src/Nodes/CircleReverseV2.cpp
+++ b/compiler/luci/import/src/Nodes/CircleReverseV2.cpp
@@ -34,8 +34,8 @@ bool CircleReverseV2GraphBuilder::validate(const ValidateArgs &args) const
return false;
const auto &tensors = args.reader.tensors();
- const auto &tensor_in = tensors.at(inputs[0]);
- const auto &tensor_axis = tensors.at(inputs[1]);
+ const auto &tensor_in = tensors.at(inputs.at(0));
+ const auto &tensor_axis = tensors.at(inputs.at(1));
const auto &tensor_out = tensors.at(outputs[0]);
switch (tensor_axis->type)
@@ -58,8 +58,8 @@ CircleNode *CircleReverseV2GraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleReverseV2>();
- node->tensor(inputs[0]);
- node->axis(inputs[1]);
+ node->tensor(inputs.at(0));
+ node->axis(inputs.at(1));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleRound.cpp b/compiler/luci/import/src/Nodes/CircleRound.cpp
index 896489521..ad77f9f03 100644
--- a/compiler/luci/import/src/Nodes/CircleRound.cpp
+++ b/compiler/luci/import/src/Nodes/CircleRound.cpp
@@ -37,7 +37,7 @@ bool CircleRoundGraphBuilder::validate(const ValidateArgs &args) const
// bfloat16, half (float16), float32, float64, complex64, complex128
// Currently, circle supports float16, float32, complex64
const auto &tensors = args.reader.tensors();
- const auto &tensor_in = tensors.at(inputs[0]);
+ const auto &tensor_in = tensors.at(inputs.at(0));
const auto &tensor_out = tensors.at(outputs[0]);
switch (tensor_in->type)
@@ -63,7 +63,7 @@ CircleNode *CircleRoundGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleRound>();
- node->x(inputs[0]);
+ node->x(inputs.at(0));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleRsqrt.cpp b/compiler/luci/import/src/Nodes/CircleRsqrt.cpp
index b5de0b575..ae05fbbf9 100644
--- a/compiler/luci/import/src/Nodes/CircleRsqrt.cpp
+++ b/compiler/luci/import/src/Nodes/CircleRsqrt.cpp
@@ -33,7 +33,7 @@ bool CircleRsqrtGraphBuilder::validate(const ValidateArgs &args) const
// bfloat16, half (float16), float32, float64, complex64, complex128
// Currently, circle supports float16, float32, complex64
const auto &tensors = args.reader.tensors();
- const auto &tensor = tensors.at(inputs[0]);
+ const auto &tensor = tensors.at(inputs.at(0));
switch (tensor->type)
{
case circle::TensorType_FLOAT16:
@@ -52,7 +52,7 @@ CircleNode *CircleRsqrtGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleRsqrt>();
- node->x(inputs[0]);
+ node->x(inputs.at(0));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleScatterNd.cpp b/compiler/luci/import/src/Nodes/CircleScatterNd.cpp
index adcaa0030..7f86aeb74 100644
--- a/compiler/luci/import/src/Nodes/CircleScatterNd.cpp
+++ b/compiler/luci/import/src/Nodes/CircleScatterNd.cpp
@@ -32,12 +32,12 @@ bool CircleScatterNdGraphBuilder::validate(const ValidateArgs &args) const
// indices must have the same type as shape
const auto &tensors = args.reader.tensors();
- if (tensors[inputs[0]]->type != tensors[inputs[2]]->type)
+ if (tensors[inputs.at(0)]->type != tensors[inputs.at(2)]->type)
return false;
// indices must be either int32 or int64
- if (tensors[inputs[0]]->type != circle::TensorType_INT32 &&
- tensors[inputs[0]]->type != circle::TensorType_INT64)
+ if (tensors[inputs.at(0)]->type != circle::TensorType_INT32 &&
+ tensors[inputs.at(0)]->type != circle::TensorType_INT64)
return false;
return true;
@@ -48,9 +48,9 @@ CircleNode *CircleScatterNdGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleScatterNd>();
- node->indices(inputs[0]);
- node->updates(inputs[1]);
- node->shape(inputs[2]);
+ node->indices(inputs.at(0));
+ node->updates(inputs.at(1));
+ node->shape(inputs.at(2));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleSegmentSum.cpp b/compiler/luci/import/src/Nodes/CircleSegmentSum.cpp
index 1122bdca3..fb84e5d52 100644
--- a/compiler/luci/import/src/Nodes/CircleSegmentSum.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSegmentSum.cpp
@@ -33,9 +33,9 @@ bool CircleSegmentSumGraphBuilder::validate(const ValidateArgs &args) const
return false;
const auto &tensors = args.reader.tensors();
- const auto &tensor_in = tensors.at(inputs[0]);
+ const auto &tensor_in = tensors.at(inputs.at(0));
const auto &tensor_out = tensors.at(outputs[0]);
- const auto &tensor_ids = tensors.at(inputs[1]);
+ const auto &tensor_ids = tensors.at(inputs.at(1));
switch (tensor_ids->type)
{
@@ -59,8 +59,8 @@ CircleNode *CircleSegmentSumGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleSegmentSum>();
- node->input(inputs[0]);
- node->segment_ids(inputs[1]);
+ node->input(inputs.at(0));
+ node->segment_ids(inputs.at(1));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleSelect.cpp b/compiler/luci/import/src/Nodes/CircleSelect.cpp
index ff94212c3..1e649f1e0 100644
--- a/compiler/luci/import/src/Nodes/CircleSelect.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSelect.cpp
@@ -33,7 +33,7 @@ bool CircleSelectGraphBuilder::validate(const ValidateArgs &args) const
return false;
const auto &tensors = args.reader.tensors();
- const auto &tensor = tensors.at(inputs[0]);
+ const auto &tensor = tensors.at(inputs.at(0));
if (tensor->type != circle::TensorType_BOOL)
return false;
// TODO check dtypes for input 1, 2
@@ -46,9 +46,9 @@ CircleNode *CircleSelectGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleSelect>();
- node->condition(inputs[0]);
- node->t(inputs[1]);
- node->e(inputs[2]);
+ node->condition(inputs.at(0));
+ node->t(inputs.at(1));
+ node->e(inputs.at(2));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleSelectV2.cpp b/compiler/luci/import/src/Nodes/CircleSelectV2.cpp
index 78b2e6459..e6dd04de0 100644
--- a/compiler/luci/import/src/Nodes/CircleSelectV2.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSelectV2.cpp
@@ -33,12 +33,12 @@ bool CircleSelectV2GraphBuilder::validate(const ValidateArgs &args) const
return false;
const auto &tensors = args.reader.tensors();
- const auto &condition = tensors.at(inputs[0]);
+ const auto &condition = tensors.at(inputs.at(0));
if (condition->type != circle::TensorType_BOOL)
return false;
- const auto &t = tensors.at(inputs[1]);
- const auto &e = tensors.at(inputs[2]);
+ const auto &t = tensors.at(inputs.at(1));
+ const auto &e = tensors.at(inputs.at(2));
if (t->type != e->type)
return false;
@@ -50,9 +50,9 @@ CircleNode *CircleSelectV2GraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleSelectV2>();
- node->condition(inputs[0]);
- node->t(inputs[1]);
- node->e(inputs[2]);
+ node->condition(inputs.at(0));
+ node->t(inputs.at(1));
+ node->e(inputs.at(2));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleShape.cpp b/compiler/luci/import/src/Nodes/CircleShape.cpp
index 864b5eb51..bd7dfc9d9 100644
--- a/compiler/luci/import/src/Nodes/CircleShape.cpp
+++ b/compiler/luci/import/src/Nodes/CircleShape.cpp
@@ -42,7 +42,7 @@ CircleNode *CircleShapeGraphBuilder::build_node(const circle::OperatorT &op,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleShape>();
- node->input(inputs[0]);
+ node->input(inputs.at(0));
const auto *options = op.builtin_options.AsShapeOptions();
node->out_type(luci_datatype(options->out_type));
diff --git a/compiler/luci/import/src/Nodes/CircleSin.cpp b/compiler/luci/import/src/Nodes/CircleSin.cpp
index 61d60c78f..4b245ef6b 100644
--- a/compiler/luci/import/src/Nodes/CircleSin.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSin.cpp
@@ -33,7 +33,7 @@ bool CircleSinGraphBuilder::validate(const ValidateArgs &args) const
// input type check
const auto &tensors = args.reader.tensors();
- const auto &tensor = tensors.at(inputs[0]);
+ const auto &tensor = tensors.at(inputs.at(0));
switch (tensor->type)
{
case circle::TensorType_FLOAT16:
@@ -53,7 +53,7 @@ CircleNode *CircleSinGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleSin>();
- node->x(inputs[0]);
+ node->x(inputs.at(0));
// No options for Sin
diff --git a/compiler/luci/import/src/Nodes/CircleSlice.cpp b/compiler/luci/import/src/Nodes/CircleSlice.cpp
index 313c35599..8601fbf21 100644
--- a/compiler/luci/import/src/Nodes/CircleSlice.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSlice.cpp
@@ -42,9 +42,9 @@ CircleNode *CircleSliceGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleSlice>();
- node->input(inputs[0]);
- node->begin(inputs[1]);
- node->size(inputs[2]);
+ node->input(inputs.at(0));
+ node->begin(inputs.at(1));
+ node->size(inputs.at(2));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleSoftmax.cpp b/compiler/luci/import/src/Nodes/CircleSoftmax.cpp
index 0d316e18c..0ef0b5418 100644
--- a/compiler/luci/import/src/Nodes/CircleSoftmax.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSoftmax.cpp
@@ -38,7 +38,7 @@ CircleNode *CircleSoftmaxGraphBuilder::build_node(const circle::OperatorT &op,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleSoftmax>();
- node->logits(inputs[0]);
+ node->logits(inputs.at(0));
const auto *options = op.builtin_options.AsSoftmaxOptions();
node->beta(options->beta);
diff --git a/compiler/luci/import/src/Nodes/CircleSpaceToBatchND.cpp b/compiler/luci/import/src/Nodes/CircleSpaceToBatchND.cpp
index f1361fb11..c1d508e3e 100644
--- a/compiler/luci/import/src/Nodes/CircleSpaceToBatchND.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSpaceToBatchND.cpp
@@ -33,7 +33,7 @@ bool CircleSpaceToBatchNDGraphBuilder::validate(const ValidateArgs &args) const
// input 1 and 2 should have INT32/INT64 type
const auto &tensors = args.reader.tensors();
- const auto &tensor_1 = tensors.at(inputs[1]);
+ const auto &tensor_1 = tensors.at(inputs.at(1));
switch (tensor_1->type)
{
case circle::TensorType_INT32:
@@ -42,7 +42,7 @@ bool CircleSpaceToBatchNDGraphBuilder::validate(const ValidateArgs &args) const
default:
return false;
}
- const auto &tensor_2 = tensors.at(inputs[2]);
+ const auto &tensor_2 = tensors.at(inputs.at(2));
switch (tensor_2->type)
{
case circle::TensorType_INT32:
@@ -53,7 +53,7 @@ bool CircleSpaceToBatchNDGraphBuilder::validate(const ValidateArgs &args) const
}
// Only support input shape dimension 3 and 4 only
- const auto &tensor_0 = tensors.at(inputs[0]);
+ const auto &tensor_0 = tensors.at(inputs.at(0));
const auto t_0_s = tensor_0->shape.size();
if (t_0_s != 3 && t_0_s != 4)
return false;
@@ -68,9 +68,9 @@ CircleNode *CircleSpaceToBatchNDGraphBuilder::build_node(const circle::OperatorT
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleSpaceToBatchND>();
- node->input(inputs[0]);
- node->block_shape(inputs[1]);
- node->paddings(inputs[2]);
+ node->input(inputs.at(0));
+ node->block_shape(inputs.at(1));
+ node->paddings(inputs.at(2));
// No options for SpaceToBatchND
diff --git a/compiler/luci/import/src/Nodes/CircleSpaceToDepth.cpp b/compiler/luci/import/src/Nodes/CircleSpaceToDepth.cpp
index b612c9a9a..8ccd55dc6 100644
--- a/compiler/luci/import/src/Nodes/CircleSpaceToDepth.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSpaceToDepth.cpp
@@ -41,7 +41,7 @@ CircleNode *CircleSpaceToDepthGraphBuilder::build_node(const circle::OperatorT &
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleSpaceToDepth>();
- node->input(inputs[0]);
+ node->input(inputs.at(0));
const auto *options = op.builtin_options.AsSpaceToDepthOptions();
node->block_size(options->block_size);
diff --git a/compiler/luci/import/src/Nodes/CircleSparseToDense.cpp b/compiler/luci/import/src/Nodes/CircleSparseToDense.cpp
index bfe790fc1..26d575e90 100644
--- a/compiler/luci/import/src/Nodes/CircleSparseToDense.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSparseToDense.cpp
@@ -36,10 +36,10 @@ CircleNode *CircleSparseToDenseGraphBuilder::build_node(const circle::OperatorT
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleSparseToDense>();
- node->indices(inputs[0]);
- node->output_shape(inputs[1]);
- node->values(inputs[2]);
- node->default_value(inputs[3]);
+ node->indices(inputs.at(0));
+ node->output_shape(inputs.at(1));
+ node->values(inputs.at(2));
+ node->default_value(inputs.at(3));
const auto *options = op.builtin_options.AsSparseToDenseOptions();
node->validate_indices(options->validate_indices);
diff --git a/compiler/luci/import/src/Nodes/CircleSqrt.cpp b/compiler/luci/import/src/Nodes/CircleSqrt.cpp
index 8a90f6691..c8beaee0d 100644
--- a/compiler/luci/import/src/Nodes/CircleSqrt.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSqrt.cpp
@@ -36,7 +36,7 @@ CircleNode *CircleSqrtGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleSqrt>();
- node->x(inputs[0]);
+ node->x(inputs.at(0));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleSquare.cpp b/compiler/luci/import/src/Nodes/CircleSquare.cpp
index 8398548b6..b5ba048d7 100644
--- a/compiler/luci/import/src/Nodes/CircleSquare.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSquare.cpp
@@ -33,7 +33,7 @@ bool CircleSquareGraphBuilder::validate(const ValidateArgs &args) const
// bfloat16, half (float16), float32, float64, complex64, complex128
// Currently, circle supports float16, float32, complex64
const auto &tensors = args.reader.tensors();
- const auto &tensor = tensors.at(inputs[0]);
+ const auto &tensor = tensors.at(inputs.at(0));
switch (tensor->type)
{
case circle::TensorType_INT32:
@@ -55,7 +55,7 @@ CircleNode *CircleSquareGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleSquare>();
- node->x(inputs[0]);
+ node->x(inputs.at(0));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleSquaredDifference.cpp b/compiler/luci/import/src/Nodes/CircleSquaredDifference.cpp
index 93ce959e2..6deae94c5 100644
--- a/compiler/luci/import/src/Nodes/CircleSquaredDifference.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSquaredDifference.cpp
@@ -37,7 +37,7 @@ bool CircleSquaredDifferenceGraphBuilder::validate(const ValidateArgs &args) con
// Inputs must be one of the following types
// bfloat16, half(float16), float32, float64, int32, int64, complex64, complex128
const auto &tensors = args.reader.tensors();
- const auto &tensor = tensors.at(inputs[0]);
+ const auto &tensor = tensors.at(inputs.at(0));
switch (tensor->type)
{
case circle::TensorType_FLOAT16:
@@ -53,11 +53,11 @@ bool CircleSquaredDifferenceGraphBuilder::validate(const ValidateArgs &args) con
}
// Input types must match
- if (tensors.at(inputs[0])->type != tensors.at(inputs[1])->type)
+ if (tensors.at(inputs.at(0))->type != tensors.at(inputs.at(1))->type)
return false;
// Input and output types must match
- if (tensors.at(inputs[0])->type != tensors.at(outputs[0])->type)
+ if (tensors.at(inputs.at(0))->type != tensors.at(outputs[0])->type)
return false;
return true;
@@ -68,8 +68,8 @@ CircleNode *CircleSquaredDifferenceGraphBuilder::build_node(const circle::Operat
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleSquaredDifference>();
- node->x(inputs[0]);
- node->y(inputs[1]);
+ node->x(inputs.at(0));
+ node->y(inputs.at(1));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleSqueeze.cpp b/compiler/luci/import/src/Nodes/CircleSqueeze.cpp
index a5252d0bb..32792c266 100644
--- a/compiler/luci/import/src/Nodes/CircleSqueeze.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSqueeze.cpp
@@ -38,7 +38,7 @@ CircleNode *CircleSqueezeGraphBuilder::build_node(const circle::OperatorT &op,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleSqueeze>();
- node->input(inputs[0]);
+ node->input(inputs.at(0));
const auto *options = op.builtin_options.AsSqueezeOptions();
assert(options);
diff --git a/compiler/luci/import/src/Nodes/CircleStridedSlice.cpp b/compiler/luci/import/src/Nodes/CircleStridedSlice.cpp
index 95e446704..8f943a682 100644
--- a/compiler/luci/import/src/Nodes/CircleStridedSlice.cpp
+++ b/compiler/luci/import/src/Nodes/CircleStridedSlice.cpp
@@ -42,10 +42,10 @@ CircleNode *CircleStridedSliceGraphBuilder::build_node(const circle::OperatorT &
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleStridedSlice>();
- node->input(inputs[0]);
- node->begin(inputs[1]);
- node->end(inputs[2]);
- node->strides(inputs[3]);
+ node->input(inputs.at(0));
+ node->begin(inputs.at(1));
+ node->end(inputs.at(2));
+ node->strides(inputs.at(3));
const auto *options = op.builtin_options.AsStridedSliceOptions();
node->begin_mask(options->begin_mask);
diff --git a/compiler/luci/import/src/Nodes/CircleSub.cpp b/compiler/luci/import/src/Nodes/CircleSub.cpp
index 968e9f51f..9acf83d40 100644
--- a/compiler/luci/import/src/Nodes/CircleSub.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSub.cpp
@@ -39,8 +39,8 @@ CircleNode *CircleSubGraphBuilder::build_node(const circle::OperatorT &op,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleSub>();
- node->x(inputs[0]);
- node->y(inputs[1]);
+ node->x(inputs.at(0));
+ node->y(inputs.at(1));
const auto *options = op.builtin_options.AsSubOptions();
node->fusedActivationFunction(luci_actfunc(options->fused_activation_function));
diff --git a/compiler/luci/import/src/Nodes/CircleSum.cpp b/compiler/luci/import/src/Nodes/CircleSum.cpp
index b4865de59..bd3cb6239 100644
--- a/compiler/luci/import/src/Nodes/CircleSum.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSum.cpp
@@ -34,8 +34,8 @@ CircleNode *CircleSumGraphBuilder::build_node(const circle::OperatorT &op,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleSum>();
- node->input(inputs[0]);
- node->reduction_indices(inputs[1]);
+ node->input(inputs.at(0));
+ node->reduction_indices(inputs.at(1));
const auto *options = op.builtin_options.AsReducerOptions();
node->keep_dims(options->keep_dims);
diff --git a/compiler/luci/import/src/Nodes/CircleTanh.cpp b/compiler/luci/import/src/Nodes/CircleTanh.cpp
index 8986378c4..018f5701b 100644
--- a/compiler/luci/import/src/Nodes/CircleTanh.cpp
+++ b/compiler/luci/import/src/Nodes/CircleTanh.cpp
@@ -28,21 +28,13 @@ bool CircleTanhGraphBuilder::validate(const ValidateArgs &args) const
const auto &inputs = args.op.inputs;
if (inputs.size() != 1)
return false;
+ const auto &outputs = args.op.outputs;
+ if (outputs.size() != 1)
+ return false;
- // Must be one of the following types
- // bfloat16, half (float16), float32, float64, complex64, complex128
- // Currently, circle supports float16, float32, complex64
const auto &tensors = args.reader.tensors();
- const auto &tensor = tensors.at(inputs[0]);
- switch (tensor->type)
- {
- case circle::TensorType_FLOAT16:
- case circle::TensorType_FLOAT32:
- case circle::TensorType_COMPLEX64:
- break;
- default:
- return false;
- }
+ if (tensors.at(inputs.at(0))->type != tensors.at(outputs[0])->type)
+ return false;
return true;
}
@@ -52,7 +44,7 @@ CircleNode *CircleTanhGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleTanh>();
- node->x(inputs[0]);
+ node->x(inputs.at(0));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleTile.cpp b/compiler/luci/import/src/Nodes/CircleTile.cpp
index 91054ce7f..bc6f320ba 100644
--- a/compiler/luci/import/src/Nodes/CircleTile.cpp
+++ b/compiler/luci/import/src/Nodes/CircleTile.cpp
@@ -34,10 +34,10 @@ bool CircleTileGraphBuilder::validate(const ValidateArgs &args) const
if (outputs.size() != 1)
return false;
- // Multiples (inputs[1]) must be one of the following types
+ // Multiples (inputs.at(1)) must be one of the following types
// int32, int64
const auto &tensors = args.reader.tensors();
- const auto &tensor = tensors.at(inputs[1]);
+ const auto &tensor = tensors.at(inputs.at(1));
switch (tensor->type)
{
case circle::TensorType_INT32:
@@ -48,7 +48,7 @@ bool CircleTileGraphBuilder::validate(const ValidateArgs &args) const
}
// Type of input and output must be the same
- if (tensors.at(inputs[0])->type != tensors.at(outputs[0])->type)
+ if (tensors.at(inputs.at(0))->type != tensors.at(outputs[0])->type)
return false;
return true;
@@ -59,8 +59,8 @@ CircleNode *CircleTileGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleTile>();
- node->input(inputs[0]);
- node->multiples(inputs[1]);
+ node->input(inputs.at(0));
+ node->multiples(inputs.at(1));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleTopKV2.cpp b/compiler/luci/import/src/Nodes/CircleTopKV2.cpp
index 5c1051c43..f0677de86 100644
--- a/compiler/luci/import/src/Nodes/CircleTopKV2.cpp
+++ b/compiler/luci/import/src/Nodes/CircleTopKV2.cpp
@@ -36,7 +36,7 @@ bool CircleTopKV2GraphBuilder::validate(const ValidateArgs &args) const
return false;
const auto &tensors = args.reader.tensors();
- const auto &tensor = tensors.at(inputs[1]);
+ const auto &tensor = tensors.at(inputs.at(1));
if (tensor->type != circle::TensorType_INT32)
return false;
diff --git a/compiler/luci/import/src/Nodes/CircleTranspose.cpp b/compiler/luci/import/src/Nodes/CircleTranspose.cpp
index 8622c8b80..cc3153085 100644
--- a/compiler/luci/import/src/Nodes/CircleTranspose.cpp
+++ b/compiler/luci/import/src/Nodes/CircleTranspose.cpp
@@ -39,8 +39,8 @@ CircleNode *CircleTransposeGraphBuilder::build_node(const circle::OperatorT &op,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleTranspose>();
- node->a(inputs[0]);
- node->perm(inputs[1]);
+ node->a(inputs.at(0));
+ node->perm(inputs.at(1));
const auto *options = op.builtin_options.AsTransposeOptions();
(void)options;
diff --git a/compiler/luci/import/src/Nodes/CircleTransposeConv.cpp b/compiler/luci/import/src/Nodes/CircleTransposeConv.cpp
index 7bdf46daa..ddb196657 100644
--- a/compiler/luci/import/src/Nodes/CircleTransposeConv.cpp
+++ b/compiler/luci/import/src/Nodes/CircleTransposeConv.cpp
@@ -30,6 +30,24 @@ bool CircleTransposeConvGraphBuilder::validate(const ValidateArgs &args) const
if (args.op.inputs.size() != 3)
return false;
+ const auto &inputs = args.op.inputs;
+ const auto &tensors = args.reader.tensors();
+ const auto &filter_tensor = tensors.at(inputs.at(1));
+ const auto &filter_shape = filter_tensor.get()->shape;
+ const auto &ifm_tensor = tensors.at(inputs.at(2));
+ const auto &ifm_shape = ifm_tensor.get()->shape;
+
+ // ifm and filters must be 4-D tensor
+ if (ifm_shape.size() != 4)
+ return false;
+ if (filter_shape.size() != 4)
+ return false;
+
+ // input shape : [batch, height, width, in_channels]
+ // filters shape : [output_channels, height, weight, in_channels]
+ if (ifm_tensor.get()->shape.at(3) != filter_tensor.get()->shape.at(3))
+ return false;
+
return true;
}
@@ -39,9 +57,9 @@ CircleNode *CircleTransposeConvGraphBuilder::build_node(const circle::OperatorT
{
auto *node = graph->nodes()->create<CircleTransposeConv>();
- node->inputSizes(inputs[0]);
- node->filter(inputs[1]);
- node->outBackprop(inputs[2]);
+ node->inputSizes(inputs.at(0));
+ node->filter(inputs.at(1));
+ node->outBackprop(inputs.at(2));
const auto *options = op.builtin_options.AsTransposeConvOptions();
node->padding(luci_padding(options->padding));
diff --git a/compiler/luci/import/src/Nodes/CircleUnique.cpp b/compiler/luci/import/src/Nodes/CircleUnique.cpp
new file mode 100644
index 000000000..5e79a2920
--- /dev/null
+++ b/compiler/luci/import/src/Nodes/CircleUnique.cpp
@@ -0,0 +1,89 @@
+/*
+ * 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 "luci/Import/Nodes/CircleUnique.h"
+
+#include <luci/IR/Nodes/CircleUnique.h>
+#include <luci/IR/Nodes/CircleUniqueOut.h>
+
+#include <loco.h>
+
+namespace luci
+{
+
+bool CircleUniqueGraphBuilder::validate(const ValidateArgs &args) const
+{
+ if (args.op.inputs.size() != 1)
+ return false;
+
+ if (args.op.outputs.size() != 2)
+ return false;
+
+ return true;
+}
+
+void CircleUniqueGraphBuilder::build(const circle::OperatorT &op,
+ GraphBuilderContext *context) const
+{
+ assert(context != nullptr);
+
+ auto graph = context->graph();
+
+ const std::vector<int32_t> &inputs = op.inputs;
+ const std::vector<int32_t> &outputs = op.outputs;
+ const auto &tensors = context->reader()->tensors();
+ auto tensors_ptr = context->reader()->tensors_ptr();
+ assert(tensors_ptr != nullptr);
+
+ std::vector<CircleNode *> input_nodes;
+ for (const int32_t input_tensor_index : inputs)
+ {
+ input_nodes.push_back(context->nodefinder()->node(input_tensor_index));
+ }
+
+ // Create CircleUnique
+ auto node = graph->nodes()->create<CircleUnique>();
+ node->input(input_nodes[0]);
+
+ const auto *options = op.builtin_options.AsUniqueOptions();
+ node->output_type(luci_datatype(options->idx_out_type));
+
+ assert(int32_t(outputs.size()) == 2);
+ // Let's use name of output 0 as Unique name
+ const circle::TensorT &output_tensor = *tensors[outputs[0]];
+ node->name(tensor_name(output_tensor));
+
+ // Create virtual outputs of Unique
+ for (int32_t n = 0; n < 2; ++n)
+ {
+ const circle::TensorT &output_tensor = *tensors[outputs[n]];
+
+ auto *nodeout = graph->nodes()->create<CircleUniqueOut>();
+ copy_tensor_attributes(output_tensor, nodeout);
+ // mark shape_status
+ if (tensors_ptr->Get(outputs[n])->shape() == nullptr)
+ nodeout->shape_status(ShapeStatus::NOSHAPE);
+ else
+ nodeout->shape_status(ShapeStatus::VALID);
+
+ nodeout->input(node);
+ nodeout->index(n);
+
+ context->nodefinder()->enroll(outputs[n], nodeout);
+ }
+}
+
+} // namespace luci
diff --git a/compiler/luci/import/src/Nodes/CircleUnpack.cpp b/compiler/luci/import/src/Nodes/CircleUnpack.cpp
index c4282e24f..9e7f3d3e1 100644
--- a/compiler/luci/import/src/Nodes/CircleUnpack.cpp
+++ b/compiler/luci/import/src/Nodes/CircleUnpack.cpp
@@ -59,7 +59,7 @@ bool CircleUnpackGraphBuilder::validate(const ValidateArgs &args) const
return false;
const auto &tensors = args.reader.tensors();
- const auto &tensor = tensors.at(inputs[0]);
+ const auto &tensor = tensors.at(inputs.at(0));
const auto &shape = tensor->shape;
auto shape_size = static_cast<int32_t>(shape.size());
if (shape_size > 0)
diff --git a/compiler/luci/import/src/Nodes/CircleWhere.cpp b/compiler/luci/import/src/Nodes/CircleWhere.cpp
index a13c4d6c9..f4c5f0c66 100644
--- a/compiler/luci/import/src/Nodes/CircleWhere.cpp
+++ b/compiler/luci/import/src/Nodes/CircleWhere.cpp
@@ -35,7 +35,7 @@ bool CircleWhereGraphBuilder::validate(const ValidateArgs &args) const
return false;
const auto &tensors = args.reader.tensors();
- const auto &tensor_condition = tensors.at(inputs[0]);
+ const auto &tensor_condition = tensors.at(inputs.at(0));
const auto &tensor_out = tensors.at(outputs[0]);
if (tensor_condition->type != circle::TensorType_BOOL)
@@ -52,7 +52,7 @@ CircleNode *CircleWhereGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleWhere>();
- node->condition(inputs[0]);
+ node->condition(inputs.at(0));
return node;
}
diff --git a/compiler/luci/import/src/Nodes/CircleZerosLike.cpp b/compiler/luci/import/src/Nodes/CircleZerosLike.cpp
index 4362925cd..e60424def 100644
--- a/compiler/luci/import/src/Nodes/CircleZerosLike.cpp
+++ b/compiler/luci/import/src/Nodes/CircleZerosLike.cpp
@@ -39,7 +39,7 @@ CircleNode *CircleZerosLikeGraphBuilder::build_node(const circle::OperatorT &,
loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleZerosLike>();
- node->input(inputs[0]);
+ node->input(inputs.at(0));
// ZerosLikeOptinos are empty
diff --git a/compiler/luci/lang/include/luci/IR/CircleNodes.h b/compiler/luci/lang/include/luci/IR/CircleNodes.h
index 3b31149b2..e57f5bb3e 100644
--- a/compiler/luci/lang/include/luci/IR/CircleNodes.h
+++ b/compiler/luci/lang/include/luci/IR/CircleNodes.h
@@ -70,10 +70,12 @@
#include "Nodes/CircleMirrorPad.h"
#include "Nodes/CircleMul.h"
#include "Nodes/CircleNeg.h"
+#include "Nodes/CircleNonMaxSuppressionV4.h"
#include "Nodes/CircleNotEqual.h"
#include "Nodes/CircleOneHot.h"
#include "Nodes/CirclePack.h"
#include "Nodes/CirclePad.h"
+#include "Nodes/CirclePadV2.h"
#include "Nodes/CirclePow.h"
#include "Nodes/CirclePRelu.h"
#include "Nodes/CircleRange.h"
@@ -117,6 +119,7 @@
#include "Nodes/CircleTopKV2.h"
#include "Nodes/CircleTranspose.h"
#include "Nodes/CircleTransposeConv.h"
+#include "Nodes/CircleUnique.h"
#include "Nodes/CircleUnpack.h"
#include "Nodes/CircleWhere.h"
#include "Nodes/CircleWhile.h"
@@ -130,7 +133,9 @@
#include "Nodes/CircleOutput.h"
#include "Nodes/CircleCustomOut.h"
#include "Nodes/CircleIfOut.h"
+#include "Nodes/CircleNonMaxSuppressionV4Out.h"
#include "Nodes/CircleUnpackOut.h"
+#include "Nodes/CircleUniqueOut.h"
#include "Nodes/CircleSplitOut.h"
#include "Nodes/CircleSplitVOut.h"
#include "Nodes/CircleTopKV2Out.h"
diff --git a/compiler/luci/lang/include/luci/IR/CircleNodes.lst b/compiler/luci/lang/include/luci/IR/CircleNodes.lst
index 488dcfb89..801051848 100644
--- a/compiler/luci/lang/include/luci/IR/CircleNodes.lst
+++ b/compiler/luci/lang/include/luci/IR/CircleNodes.lst
@@ -22,7 +22,6 @@ CIRCLE_NODE(BATCHMATMUL, luci::CircleBatchMatMul)
CIRCLE_NODE(CAST, luci::CircleCast)
CIRCLE_NODE(CEIL, luci::CircleCeil)
CIRCLE_NODE(CONCATENATION, luci::CircleConcatenation)
-CIRCLE_NODE(CONST, luci::CircleConst)
CIRCLE_NODE(CONV_2D, luci::CircleConv2D)
CIRCLE_NODE(COS, luci::CircleCos)
CIRCLE_NODE(CUSTOM, luci::CircleCustom)
@@ -64,10 +63,12 @@ CIRCLE_NODE(MINIMUM, luci::CircleMinimum)
CIRCLE_NODE(MIRROR_PAD, luci::CircleMirrorPad)
CIRCLE_NODE(MUL, luci::CircleMul)
CIRCLE_NODE(NEG, luci::CircleNeg)
+CIRCLE_NODE(NON_MAX_SUPPRESSION_V4, luci::CircleNonMaxSuppressionV4)
CIRCLE_NODE(NOT_EQUAL, luci::CircleNotEqual)
CIRCLE_NODE(ONE_HOT, luci::CircleOneHot)
CIRCLE_NODE(PACK, luci::CirclePack)
CIRCLE_NODE(PAD, luci::CirclePad)
+CIRCLE_NODE(PADV2, luci::CirclePadV2)
CIRCLE_NODE(POW, luci::CirclePow)
CIRCLE_NODE(PRELU, luci::CirclePRelu)
CIRCLE_NODE(RANGE, luci::CircleRange)
@@ -111,6 +112,7 @@ CIRCLE_NODE(TILE, luci::CircleTile)
CIRCLE_NODE(TOPK_V2, luci::CircleTopKV2)
CIRCLE_NODE(TRANSPOSE, luci::CircleTranspose)
CIRCLE_NODE(TRANSPOSE_CONV, luci::CircleTransposeConv)
+CIRCLE_NODE(UNIQUE, luci::CircleUnique)
CIRCLE_NODE(UNPACK, luci::CircleUnpack)
CIRCLE_NODE(WHERE, luci::CircleWhere)
CIRCLE_NODE(WHILE, luci::CircleWhile)
@@ -120,14 +122,17 @@ CIRCLE_NODE(BCQ_FULLY_CONNECTED, luci::CircleBCQFullyConnected)
CIRCLE_NODE(BCQ_GATHER, luci::CircleBCQGather)
CIRCLE_NODE(INSTANCE_NORM, luci::CircleInstanceNorm)
// Virtual node(s)
+CIRCLE_NODE(CIRCLECONST, luci::CircleConst)
CIRCLE_NODE(CIRCLEINPUT, luci::CircleInput)
CIRCLE_NODE(CIRCLEOUTPUT, luci::CircleOutput)
CIRCLE_NODE(CIRCLEOUTPUTDUMMY, luci::CircleOutputDummy)
CIRCLE_NODE(CIRCLEOUTPUTEXCLUDE, luci::CircleOutputExclude)
CIRCLE_NODE(CIRCLECUSTOMOUT, luci::CircleCustomOut)
CIRCLE_NODE(CIRCLEIFOUT, luci::CircleIfOut)
+CIRCLE_NODE(CIRCLENONMAXSUPPRESSIONV4OUT, luci::CircleNonMaxSuppressionV4Out)
CIRCLE_NODE(CIRCLESPLITOUT, luci::CircleSplitOut)
CIRCLE_NODE(CIRCLESPLITVOUT, luci::CircleSplitVOut)
CIRCLE_NODE(CIRCLETOPKV2OUT, luci::CircleTopKV2Out)
+CIRCLE_NODE(CIRCLEUNIQUEOUT, luci::CircleUniqueOut)
CIRCLE_NODE(CIRCLEUNPACKOUT, luci::CircleUnpackOut)
CIRCLE_NODE(CIRCLEWHILEOUT, luci::CircleWhileOut)
diff --git a/compiler/luci/lang/include/luci/IR/CircleQuantParam.h b/compiler/luci/lang/include/luci/IR/CircleQuantParam.h
index 7253e657b..694437303 100644
--- a/compiler/luci/lang/include/luci/IR/CircleQuantParam.h
+++ b/compiler/luci/lang/include/luci/IR/CircleQuantParam.h
@@ -29,6 +29,7 @@ struct CircleQuantParam
std::vector<float> max;
std::vector<float> scale;
std::vector<int64_t> zerop;
+ int32_t quantized_dimension{0};
};
} // namespace luci
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleConst.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleConst.h
index fc671746f..250282049 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleConst.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleConst.h
@@ -31,7 +31,7 @@ namespace luci
* @brief Class to build tensor data
* @note This will not be exported as a specific op
*/
-class CircleConst final : public FixedArityNode<0, CircleNodeImpl<CircleOpcode::CONST>>
+class CircleConst final : public FixedArityNode<0, CircleNodeImpl<CircleOpcode::CIRCLECONST>>
{
public:
CircleConst() = default;
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleNonMaxSuppressionV4.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleNonMaxSuppressionV4.h
new file mode 100644
index 000000000..69f3368c0
--- /dev/null
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleNonMaxSuppressionV4.h
@@ -0,0 +1,53 @@
+/*
+ * 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_IR_CIRCLE_NON_MAX_SUPPRESSION_V4_H__
+#define __LUCI_IR_CIRCLE_NON_MAX_SUPPRESSION_V4_H__
+
+#include "luci/IR/CircleNodeDecl.h"
+#include "luci/IR/CircleOpcode.h"
+
+#include "luci/IR/LuciNodeMixins.h"
+
+namespace luci
+{
+
+/**
+ * @brief NON_MAX_SUPPRESSION_V4 in Circle
+ */
+class CircleNonMaxSuppressionV4 final
+ : public FixedArityNode<5, CircleNodeImpl<CircleOpcode::NON_MAX_SUPPRESSION_V4>>
+{
+public:
+ loco::Node *boxes(void) const { return at(0)->node(); }
+ void boxes(loco::Node *node) { at(0)->node(node); }
+
+ loco::Node *scores(void) const { return at(1)->node(); }
+ void scores(loco::Node *node) { at(1)->node(node); }
+
+ loco::Node *max_output_size(void) const { return at(2)->node(); }
+ void max_output_size(loco::Node *node) { at(2)->node(node); }
+
+ loco::Node *iou_threshold(void) const { return at(3)->node(); }
+ void iou_threshold(loco::Node *node) { at(3)->node(node); }
+
+ loco::Node *score_threshold(void) const { return at(4)->node(); }
+ void score_threshold(loco::Node *node) { at(4)->node(node); }
+};
+
+} // namespace luci
+
+#endif // __LUCI_IR_CIRCLE_NON_MAX_SUPPRESSION_V4_H__
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleNonMaxSuppressionV4Out.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleNonMaxSuppressionV4Out.h
new file mode 100644
index 000000000..a24dc3e9c
--- /dev/null
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleNonMaxSuppressionV4Out.h
@@ -0,0 +1,51 @@
+/*
+ * 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_IR_CIRCLE_NONMAXSUPPRESSIONV4OUT_H__
+#define __LUCI_IR_CIRCLE_NONMAXSUPPRESSIONV4OUT_H__
+
+#include "luci/IR/CircleNodeDecl.h"
+#include "luci/IR/CircleOpcode.h"
+
+#include "luci/IR/LuciNodeMixins.h"
+
+namespace luci
+{
+
+/**
+ * @brief Virtual NONMAXSUPPRESSIONV4OUT in Circle
+ */
+class CircleNonMaxSuppressionV4Out final
+ : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::CIRCLENONMAXSUPPRESSIONV4OUT>>
+{
+public:
+ CircleNonMaxSuppressionV4Out() = default;
+
+public:
+ loco::Node *input(void) const { return at(0)->node(); }
+ void input(loco::Node *node) { at(0)->node(node); }
+
+public:
+ int32_t index(void) const { return _index; }
+ void index(int32_t index) { _index = index; }
+
+private:
+ int32_t _index{-1};
+};
+
+} // namespace luci
+
+#endif // __LUCI_IR_CIRCLE_NONMAXSUPPRESSIONV4OUT_H__
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CirclePadV2.h b/compiler/luci/lang/include/luci/IR/Nodes/CirclePadV2.h
new file mode 100644
index 000000000..563cfd9a4
--- /dev/null
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CirclePadV2.h
@@ -0,0 +1,49 @@
+/*
+ * 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_IR_CIRCLEPADV2_H__
+#define __LUCI_IR_CIRCLEPADV2_H__
+
+#include "luci/IR/CircleNodeDecl.h"
+#include "luci/IR/CircleOpcode.h"
+
+#include "luci/IR/LuciNodeMixins.h"
+
+namespace luci
+{
+
+/**
+ * @brief PADV2 in Circle
+ */
+class CirclePadV2 final : public FixedArityNode<3, CircleNodeImpl<CircleOpcode::PADV2>>
+{
+public:
+ CirclePadV2() = default;
+
+public:
+ loco::Node *input(void) const { return at(0)->node(); }
+ void input(loco::Node *node) { at(0)->node(node); }
+
+ loco::Node *paddings(void) const { return at(1)->node(); }
+ void paddings(loco::Node *node) { at(1)->node(node); }
+
+ loco::Node *constant_values(void) const { return at(2)->node(); }
+ void constant_values(loco::Node *node) { at(2)->node(node); }
+};
+
+} // namespace luci
+
+#endif // __LUCI_IR_CIRCLEPADV2_H__
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleUnique.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleUnique.h
new file mode 100644
index 000000000..719a72362
--- /dev/null
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleUnique.h
@@ -0,0 +1,47 @@
+/*
+ * 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_IR_CIRCELUNIQUE_H__
+#define __LUCI_IR_CIRCELUNIQUE_H__
+
+#include "luci/IR/CircleNodeDecl.h"
+#include "luci/IR/CircleOpcode.h"
+
+#include "luci/IR/LuciNodeMixins.h"
+
+namespace luci
+{
+
+/**
+ * @brief Unique in Circle
+ */
+class CircleUnique final : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::UNIQUE>>
+{
+public:
+ loco::Node *input(void) const { return at(0)->node(); }
+ void input(loco::Node *node) { at(0)->node(node); }
+
+public:
+ loco::DataType idx_out_type(void) const { return _idx_out_type; }
+ void output_type(loco::DataType ot) { _idx_out_type = ot; }
+
+private:
+ loco::DataType _idx_out_type{loco::DataType::S32};
+};
+
+} // namespace luci
+
+#endif // __LUCI_IR_CIRCELUNIQUE_H__
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleUniqueOut.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleUniqueOut.h
new file mode 100644
index 000000000..f846403e0
--- /dev/null
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleUniqueOut.h
@@ -0,0 +1,51 @@
+/*
+ * 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_IR_CIRCLE_UNIQUEOUT_H__
+#define __LUCI_IR_CIRCLE_UNIQUEOUT_H__
+
+#include "luci/IR/CircleNodeDecl.h"
+#include "luci/IR/CircleOpcode.h"
+
+#include "luci/IR/LuciNodeMixins.h"
+
+namespace luci
+{
+
+/**
+ * @brief Virtual CIRCLEUNIQUEOUT in Circle
+ */
+class CircleUniqueOut final
+ : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::CIRCLEUNIQUEOUT>>
+{
+public:
+ CircleUniqueOut() = default;
+
+public:
+ loco::Node *input(void) const { return at(0)->node(); }
+ void input(loco::Node *node) { at(0)->node(node); }
+
+public:
+ int32_t index(void) const { return _index; }
+ void index(int32_t index) { _index = index; }
+
+private:
+ int32_t _index{-1};
+};
+
+} // namespace luci
+
+#endif // __LUCI_IR_CIRCLE_UNIQUEOUT_H__
diff --git a/compiler/luci/lang/src/Module.test.cpp b/compiler/luci/lang/src/Module.test.cpp
index 26bf073be..a5973e52d 100644
--- a/compiler/luci/lang/src/Module.test.cpp
+++ b/compiler/luci/lang/src/Module.test.cpp
@@ -22,7 +22,7 @@ TEST(ModuleTest, consturctor)
{
auto gs = luci::make_module();
- GTEST_SUCCEED();
+ SUCCEED();
}
TEST(ModuleTest, add)
diff --git a/compiler/luci/lang/src/Nodes/CircleCustom.test.cpp b/compiler/luci/lang/src/Nodes/CircleCustom.test.cpp
index 74ea82c6c..c07268cbf 100644
--- a/compiler/luci/lang/src/Nodes/CircleCustom.test.cpp
+++ b/compiler/luci/lang/src/Nodes/CircleCustom.test.cpp
@@ -35,7 +35,12 @@ TEST(CircleCustomTest, constructor)
ASSERT_EQ(0, custom_node.custom_code().size());
}
-TEST(CircleCustomTest, constructor_NEG) { ASSERT_DEBUG_DEATH(luci::CircleCustom{0}, ""); }
+TEST(CircleCustomTest, constructor_NEG)
+{
+ ASSERT_DEBUG_DEATH(luci::CircleCustom{0}, "");
+
+ SUCCEED();
+}
TEST(CircleCustomTest, invalidIndex_NEG)
{
diff --git a/compiler/luci/lang/src/Nodes/CircleIf.test.cpp b/compiler/luci/lang/src/Nodes/CircleIf.test.cpp
index e3c8c9f60..35f28e9ac 100644
--- a/compiler/luci/lang/src/Nodes/CircleIf.test.cpp
+++ b/compiler/luci/lang/src/Nodes/CircleIf.test.cpp
@@ -41,11 +41,15 @@ TEST(CircleIfTest, constructor)
TEST(CircleIfTestDeath, invalid_arity_NEG)
{
ASSERT_DEBUG_DEATH(luci::CircleIf very_long_name_if_node(0, 1), "");
+
+ SUCCEED();
}
TEST(CircleIfTestDeath, invalid_output_count_NEG)
{
ASSERT_DEBUG_DEATH(luci::CircleIf if_node(2, 0), "");
+
+ SUCCEED();
}
TEST(CircleIfTestDeath, invalid_input_get_index_NEG)
diff --git a/compiler/luci/lang/src/Nodes/CircleNonMaxSuppressionV4.test.cpp b/compiler/luci/lang/src/Nodes/CircleNonMaxSuppressionV4.test.cpp
new file mode 100644
index 000000000..b25ce4d6d
--- /dev/null
+++ b/compiler/luci/lang/src/Nodes/CircleNonMaxSuppressionV4.test.cpp
@@ -0,0 +1,96 @@
+/*
+ * 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 "luci/IR/Nodes/CircleNonMaxSuppressionV4.h"
+
+#include "luci/IR/CircleDialect.h"
+#include "luci/IR/CircleNodeVisitor.h"
+
+#include <gtest/gtest.h>
+
+TEST(CircleNonMaxSuppressionV4Test, constructor)
+{
+ luci::CircleNonMaxSuppressionV4 nmsv4_node;
+
+ ASSERT_EQ(luci::CircleDialect::get(), nmsv4_node.dialect());
+ ASSERT_EQ(luci::CircleOpcode::NON_MAX_SUPPRESSION_V4, nmsv4_node.opcode());
+
+ ASSERT_EQ(nullptr, nmsv4_node.boxes());
+ ASSERT_EQ(nullptr, nmsv4_node.scores());
+ ASSERT_EQ(nullptr, nmsv4_node.max_output_size());
+ ASSERT_EQ(nullptr, nmsv4_node.iou_threshold());
+ ASSERT_EQ(nullptr, nmsv4_node.score_threshold());
+}
+
+TEST(CircleNonMaxSuppressionV4Test, input_NEG)
+{
+ luci::CircleNonMaxSuppressionV4 nmsv4_node;
+ luci::CircleNonMaxSuppressionV4 node;
+
+ nmsv4_node.boxes(&node);
+ nmsv4_node.scores(&node);
+ nmsv4_node.max_output_size(&node);
+ nmsv4_node.iou_threshold(&node);
+ nmsv4_node.score_threshold(&node);
+ ASSERT_NE(nullptr, nmsv4_node.boxes());
+ ASSERT_NE(nullptr, nmsv4_node.scores());
+ ASSERT_NE(nullptr, nmsv4_node.max_output_size());
+ ASSERT_NE(nullptr, nmsv4_node.iou_threshold());
+ ASSERT_NE(nullptr, nmsv4_node.score_threshold());
+
+ nmsv4_node.boxes(nullptr);
+ nmsv4_node.scores(nullptr);
+ nmsv4_node.max_output_size(nullptr);
+ nmsv4_node.iou_threshold(nullptr);
+ nmsv4_node.score_threshold(nullptr);
+ ASSERT_EQ(nullptr, nmsv4_node.boxes());
+ ASSERT_EQ(nullptr, nmsv4_node.scores());
+ ASSERT_EQ(nullptr, nmsv4_node.max_output_size());
+ ASSERT_EQ(nullptr, nmsv4_node.iou_threshold());
+ ASSERT_EQ(nullptr, nmsv4_node.score_threshold());
+}
+
+TEST(CircleNonMaxSuppressionV4Test, arity_NEG)
+{
+ luci::CircleNonMaxSuppressionV4 nmsv4_node;
+
+ ASSERT_NO_THROW(nmsv4_node.arg(4));
+ ASSERT_THROW(nmsv4_node.arg(5), std::out_of_range);
+}
+
+TEST(CircleNonMaxSuppressionV4Test, visit_mutable_NEG)
+{
+ struct TestVisitor final : public luci::CircleNodeMutableVisitor<void>
+ {
+ };
+
+ luci::CircleNonMaxSuppressionV4 nmsv4_node;
+
+ TestVisitor tv;
+ ASSERT_THROW(nmsv4_node.accept(&tv), std::exception);
+}
+
+TEST(CircleNonMaxSuppressionV4Test, visit_NEG)
+{
+ struct TestVisitor final : public luci::CircleNodeVisitor<void>
+ {
+ };
+
+ luci::CircleNonMaxSuppressionV4 nmsv4_node;
+
+ TestVisitor tv;
+ ASSERT_THROW(nmsv4_node.accept(&tv), std::exception);
+}
diff --git a/compiler/luci/lang/src/Nodes/CircleNonMaxSuppressionV4Out.test.cpp b/compiler/luci/lang/src/Nodes/CircleNonMaxSuppressionV4Out.test.cpp
new file mode 100644
index 000000000..c6cef4e91
--- /dev/null
+++ b/compiler/luci/lang/src/Nodes/CircleNonMaxSuppressionV4Out.test.cpp
@@ -0,0 +1,32 @@
+/*
+ * 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 "luci/IR/Nodes/CircleNonMaxSuppressionV4Out.h"
+
+#include "luci/IR/CircleDialect.h"
+
+#include <gtest/gtest.h>
+
+TEST(CircleNonMaxSuppressionV4OutTest, constructor)
+{
+ luci::CircleNonMaxSuppressionV4Out vout_node;
+
+ ASSERT_EQ(luci::CircleDialect::get(), vout_node.dialect());
+ ASSERT_EQ(luci::CircleOpcode::CIRCLENONMAXSUPPRESSIONV4OUT, vout_node.opcode());
+
+ ASSERT_EQ(nullptr, vout_node.input());
+ ASSERT_EQ(-1, vout_node.index());
+}
diff --git a/compiler/luci/lang/src/Nodes/CirclePadV2.test.cpp b/compiler/luci/lang/src/Nodes/CirclePadV2.test.cpp
new file mode 100644
index 000000000..e09d517b2
--- /dev/null
+++ b/compiler/luci/lang/src/Nodes/CirclePadV2.test.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/IR/Nodes/CirclePadV2.h"
+
+#include "luci/IR/CircleDialect.h"
+#include "luci/IR/CircleNodeVisitor.h"
+
+#include <gtest/gtest.h>
+
+TEST(CirclePadV2Test, constructor_P)
+{
+ luci::CirclePadV2 node;
+
+ ASSERT_EQ(luci::CircleDialect::get(), node.dialect());
+ ASSERT_EQ(luci::CircleOpcode::PADV2, node.opcode());
+
+ ASSERT_EQ(nullptr, node.input());
+ ASSERT_EQ(nullptr, node.paddings());
+ ASSERT_EQ(nullptr, node.constant_values());
+}
+
+TEST(CirclePadV2Test, input_NEG)
+{
+ luci::CirclePadV2 pad_node;
+ luci::CirclePadV2 node;
+
+ pad_node.input(&node);
+ pad_node.paddings(&node);
+ pad_node.constant_values(&node);
+ ASSERT_NE(nullptr, pad_node.input());
+ ASSERT_NE(nullptr, pad_node.paddings());
+ ASSERT_NE(nullptr, pad_node.constant_values());
+
+ pad_node.input(nullptr);
+ pad_node.paddings(nullptr);
+ pad_node.constant_values(nullptr);
+ ASSERT_EQ(nullptr, pad_node.input());
+ ASSERT_EQ(nullptr, pad_node.paddings());
+ ASSERT_EQ(nullptr, pad_node.constant_values());
+}
+
+TEST(CirclePadV2Test, arity_NEG)
+{
+ luci::CirclePadV2 pad_node;
+
+ ASSERT_NO_THROW(pad_node.arg(2));
+ ASSERT_THROW(pad_node.arg(3), std::out_of_range);
+}
+
+TEST(CirclePadV2Test, visit_mutable_NEG)
+{
+ struct TestVisitor final : public luci::CircleNodeMutableVisitor<void>
+ {
+ };
+
+ luci::CirclePadV2 pad_node;
+
+ TestVisitor tv;
+ ASSERT_THROW(pad_node.accept(&tv), std::exception);
+}
+
+TEST(CirclePadV2Test, visit_NEG)
+{
+ struct TestVisitor final : public luci::CircleNodeVisitor<void>
+ {
+ };
+
+ luci::CirclePadV2 pad_node;
+
+ TestVisitor tv;
+ ASSERT_THROW(pad_node.accept(&tv), std::exception);
+}
diff --git a/compiler/luci/lang/src/Nodes/CircleUnique.test.cpp b/compiler/luci/lang/src/Nodes/CircleUnique.test.cpp
new file mode 100644
index 000000000..517ee97d5
--- /dev/null
+++ b/compiler/luci/lang/src/Nodes/CircleUnique.test.cpp
@@ -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 "luci/IR/Nodes/CircleUnique.h"
+
+#include "luci/IR/CircleDialect.h"
+#include "luci/IR/CircleNodeVisitor.h"
+
+#include <gtest/gtest.h>
+
+TEST(CircleUniqueTest, constructor)
+{
+ luci::CircleUnique unique_node;
+
+ ASSERT_EQ(luci::CircleDialect::get(), unique_node.dialect());
+ ASSERT_EQ(luci::CircleOpcode::UNIQUE, unique_node.opcode());
+
+ ASSERT_EQ(nullptr, unique_node.input());
+}
+
+TEST(CircleUniqueTest, input_NEG)
+{
+ luci::CircleUnique unique_node;
+ luci::CircleUnique node;
+
+ unique_node.input(&node);
+ ASSERT_NE(nullptr, unique_node.input());
+
+ unique_node.input(nullptr);
+ ASSERT_EQ(nullptr, unique_node.input());
+}
+
+TEST(CircleUniqueTest, arity_NEG)
+{
+ luci::CircleUnique unique_node;
+
+ ASSERT_NO_THROW(unique_node.arg(0));
+ ASSERT_THROW(unique_node.arg(1), std::out_of_range);
+}
+
+TEST(CircleUniqueTest, visit_mutable_NEG)
+{
+ struct TestVisitor final : public luci::CircleNodeMutableVisitor<void>
+ {
+ };
+
+ luci::CircleUnique unique_node;
+
+ TestVisitor tv;
+ ASSERT_THROW(unique_node.accept(&tv), std::exception);
+}
+
+TEST(CircleUniqueTest, visit_NEG)
+{
+ struct TestVisitor final : public luci::CircleNodeVisitor<void>
+ {
+ };
+
+ luci::CircleUnique unique_node;
+
+ TestVisitor tv;
+ ASSERT_THROW(unique_node.accept(&tv), std::exception);
+}
diff --git a/compiler/luci/lang/src/Nodes/CircleWhile.test.cpp b/compiler/luci/lang/src/Nodes/CircleWhile.test.cpp
index 19290c0a2..913686fbd 100644
--- a/compiler/luci/lang/src/Nodes/CircleWhile.test.cpp
+++ b/compiler/luci/lang/src/Nodes/CircleWhile.test.cpp
@@ -41,11 +41,15 @@ TEST(CircleWhileTest, constructor)
TEST(CircleWhileTestDeath, invalid_arity_NEG)
{
ASSERT_DEBUG_DEATH(luci::CircleWhile very_long_name_while_node(0, 1), "");
+
+ SUCCEED();
}
TEST(CircleWhileTestDeath, invalid_output_count_NEG)
{
ASSERT_DEBUG_DEATH(luci::CircleWhile while_node(2, 0), "");
+
+ SUCCEED();
}
TEST(CircleWhileTestDeath, invalid_input_get_index_NEG)
diff --git a/compiler/luci/logex/src/FormattedGraph.cpp b/compiler/luci/logex/src/FormattedGraph.cpp
index 4725ee3df..f04a418ef 100644
--- a/compiler/luci/logex/src/FormattedGraph.cpp
+++ b/compiler/luci/logex/src/FormattedGraph.cpp
@@ -244,6 +244,7 @@ private:
IMPLEMENT(luci::CircleMirrorPad)
IMPLEMENT(luci::CircleMul)
IMPLEMENT(luci::CircleNeg)
+ IMPLEMENT(luci::CircleNonMaxSuppressionV4)
IMPLEMENT(luci::CircleNotEqual)
IMPLEMENT(luci::CircleOneHot)
IMPLEMENT(luci::CirclePack)
@@ -291,6 +292,7 @@ private:
IMPLEMENT(luci::CircleTopKV2)
IMPLEMENT(luci::CircleTranspose)
IMPLEMENT(luci::CircleTransposeConv)
+ IMPLEMENT(luci::CircleUnique)
IMPLEMENT(luci::CircleUnpack)
IMPLEMENT(luci::CircleWhere)
IMPLEMENT(luci::CircleWhile)
@@ -303,9 +305,11 @@ private:
IMPLEMENT(luci::CircleInput)
IMPLEMENT(luci::CircleOutput)
IMPLEMENT(luci::CircleIfOut)
+ IMPLEMENT(luci::CircleNonMaxSuppressionV4Out)
IMPLEMENT(luci::CircleSplitOut)
IMPLEMENT(luci::CircleSplitVOut)
IMPLEMENT(luci::CircleTopKV2Out)
+ IMPLEMENT(luci::CircleUniqueOut)
IMPLEMENT(luci::CircleUnpackOut)
IMPLEMENT(luci::CircleWhileOut)
#undef IMPLEMENT
@@ -823,6 +827,19 @@ bool CircleNodeSummaryBuilder::summary(const luci::CircleNeg *node, locop::NodeS
return use_x(tbl(), node, s);
}
+bool CircleNodeSummaryBuilder::summary(const luci::CircleNonMaxSuppressionV4 *node,
+ locop::NodeSummary &s) const
+{
+ s.args().append("boxes", pepper::str(node->boxes()));
+ s.args().append("scores", pepper::str(node->scores()));
+ s.args().append("max_output_size", pepper::str(node->max_output_size()));
+ s.args().append("iou_threshold", pepper::str(node->iou_threshold()));
+ s.args().append("score_threshold", pepper::str(node->score_threshold()));
+
+ s.state(locop::NodeSummary::State::Complete);
+ return true;
+}
+
bool CircleNodeSummaryBuilder::summary(const luci::CircleNotEqual *node,
locop::NodeSummary &s) const
{
@@ -1227,6 +1244,14 @@ bool CircleNodeSummaryBuilder::summary(const luci::CircleTransposeConv *node,
return true;
}
+bool CircleNodeSummaryBuilder::summary(const luci::CircleUnique *node, locop::NodeSummary &s) const
+{
+ s.args().append("input", tbl()->lookup(node->input()));
+ s.args().append("idx_out_type", to_str(node->idx_out_type()));
+ s.state(locop::NodeSummary::State::Complete);
+ return true;
+}
+
bool CircleNodeSummaryBuilder::summary(const luci::CircleUnpack *node, locop::NodeSummary &s) const
{
s.args().append("value", tbl()->lookup(node->value()));
@@ -1293,6 +1318,16 @@ bool CircleNodeSummaryBuilder::summary(const luci::CircleTopKV2Out *node,
return true;
}
+bool CircleNodeSummaryBuilder::summary(const luci::CircleUniqueOut *node,
+ locop::NodeSummary &s) const
+{
+ s.args().append("unique", tbl()->lookup(node->input()));
+
+ s.state(locop::NodeSummary::State::Complete);
+
+ return true;
+}
+
bool CircleNodeSummaryBuilder::summary(const luci::CircleUnpackOut *node,
locop::NodeSummary &s) const
{
@@ -1308,6 +1343,12 @@ bool CircleNodeSummaryBuilder::summary(const luci::CircleIfOut *node, locop::Nod
return use_input(tbl(), node, s);
}
+bool CircleNodeSummaryBuilder::summary(const luci::CircleNonMaxSuppressionV4Out *node,
+ locop::NodeSummary &s) const
+{
+ return use_input(tbl(), node, s);
+}
+
bool CircleNodeSummaryBuilder::summary(const luci::CircleWhileOut *node,
locop::NodeSummary &s) const
{
diff --git a/compiler/luci/pass/src/CircleOptimizer.cpp b/compiler/luci/pass/src/CircleOptimizer.cpp
index 90fbe9009..2edf7a9c6 100644
--- a/compiler/luci/pass/src/CircleOptimizer.cpp
+++ b/compiler/luci/pass/src/CircleOptimizer.cpp
@@ -145,7 +145,7 @@ void CircleOptimizer::quantize(loco::Graph *g) const
{
static const std::vector<std::string> fakeq_supported_input_dtype{"float32"};
static const std::vector<std::string> fakeq_supported_output_dtype{"uint8"};
- static const std::vector<std::string> fakeq_supported_granularity{"layer"};
+ static const std::vector<std::string> fakeq_supported_granularity{"layer", "channel"};
auto input_dtype = _options->param(Options::AlgorithmParameters::Quantize_input_dtype);
auto output_dtype = _options->param(Options::AlgorithmParameters::Quantize_output_dtype);
@@ -173,7 +173,7 @@ void CircleOptimizer::quantize(loco::Graph *g) const
{
static const std::vector<std::string> qwmm_supported_input_dtype{"float32"};
static const std::vector<std::string> qwmm_supported_output_dtype{"uint8"};
- static const std::vector<std::string> qwmm_supported_granularity{"layer"};
+ static const std::vector<std::string> qwmm_supported_granularity{"layer", "channel"};
auto input_dtype = _options->param(Options::AlgorithmParameters::Quantize_input_dtype);
auto output_dtype = _options->param(Options::AlgorithmParameters::Quantize_output_dtype);
diff --git a/compiler/luci/pass/src/FuseBCQPass.cpp b/compiler/luci/pass/src/FuseBCQPass.cpp
index b81db8827..260de5b30 100644
--- a/compiler/luci/pass/src/FuseBCQPass.cpp
+++ b/compiler/luci/pass/src/FuseBCQPass.cpp
@@ -53,6 +53,11 @@ const std::string node_name_prefix(luci::NodeName node_name)
const auto index = prefix.find("Tensordot/");
prefix = prefix.substr(0, index - 1);
}
+ else if (prefix.find("/MatMul") != std::string::npos)
+ {
+ const auto index = prefix.find("/MatMul");
+ prefix = prefix.substr(0, index);
+ }
else if (prefix.find("kernel/") != std::string::npos)
{
const auto index = prefix.find("kernel/");
@@ -67,14 +72,190 @@ const std::string node_name_prefix(luci::NodeName node_name)
return prefix;
}
+/**
+ * @brief Create CircleOutputExclude operation, which has same shape and dtype with
+ * original circle_node.
+ */
+luci::CircleOutputExclude *createNoOp(luci::CircleNode *circle_node)
+{
+ auto graph = circle_node->graph();
+ auto noOp = graph->nodes()->create<luci::CircleOutputExclude>();
+
+ if (circle_node->shape_status() == luci::ShapeStatus::VALID)
+ {
+ noOp->dtype(circle_node->dtype());
+ noOp->rank(circle_node->rank());
+ for (uint32_t i = 0; i < circle_node->rank(); ++i)
+ noOp->dim(i) = circle_node->dim(i);
+ }
+ else
+ {
+ // For type inference
+ noOp->dtype(loco::DataType::FLOAT32);
+ }
+
+ return noOp;
+};
+
} // namespace
namespace
{
-class BCQConverter final
+// V means the version of BCQ.
+template <int32_t V> class BCQFuser;
+
+template <> class BCQFuser<1>
{
public:
+ bool fuseBCQ(loco::Graph *g)
+ {
+ bool changed = false;
+
+ for (auto node : loco::all_nodes(g))
+ {
+ if (auto circle_const = dynamic_cast<luci::CircleConst *>(node))
+ {
+ add_BCQ_info_node(circle_const);
+ }
+ }
+
+ if (!is_bcqinfo_valid())
+ return false;
+
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ {
+ if (auto gather = dynamic_cast<luci::CircleGather *>(node))
+ {
+ auto params = dynamic_cast<luci::CircleConst *>(gather->params());
+ if (params != nullptr && has_BCQ_info(params))
+ {
+ auto bcq_gather = g->nodes()->create<luci::CircleBCQGather>();
+
+ bcq_gather->op_version(1);
+ bcq_gather->input_scales(get_alpha(params));
+ bcq_gather->input_binary(get_packed_binary_code(params));
+ bcq_gather->indices(gather->indices());
+ bcq_gather->input_clusters(packed_clusters(params));
+
+ // input_binary shape : [output_size, hidden_size]
+ const auto binary_hidden_size =
+ loco::must_cast<luci::CircleConst *>(bcq_gather->input_binary())->dim(1).value() * 32;
+ bcq_gather->input_hidden_size(binary_hidden_size);
+
+ if (do_w_x(params))
+ {
+ bcq_gather->axis(gather->axis());
+ }
+ else
+ {
+ const auto axis_transpose = (gather->axis() == 0) ? 1 : 0;
+ bcq_gather->axis(axis_transpose);
+ }
+
+ loco::replace(gather).with(bcq_gather);
+
+ changed = true;
+ }
+ }
+ else if (auto fully_connected = dynamic_cast<luci::CircleFullyConnected *>(node))
+ {
+ auto weights = dynamic_cast<luci::CircleConst *>(fully_connected->weights());
+ if (weights != nullptr && has_BCQ_info(weights))
+ {
+ auto bcq_fc = g->nodes()->create<luci::CircleBCQFullyConnected>();
+
+ bcq_fc->op_version(1);
+ bcq_fc->weights_scales(get_alpha(weights));
+ bcq_fc->weights_binary(get_packed_binary_code(weights));
+ bcq_fc->bias(fully_connected->bias());
+ bcq_fc->weights_clusters(packed_clusters(weights));
+ bcq_fc->fusedActivationFunction(fully_connected->fusedActivationFunction());
+
+ loco::Node *bcq_input = fully_connected->input();
+ int32_t batch_rank = 0;
+
+ // If input of BCQFullyConnected has more than rank 2, we should reshape it as rank 2
+ const auto original_input = loco::must_cast<luci::CircleNode *>(fully_connected->input());
+ if (original_input->shape_status() == luci::ShapeStatus::VALID &&
+ original_input->rank() > 2)
+ {
+ auto new_shape = g->nodes()->create<luci::CircleConst>();
+ new_shape->dtype(loco::DataType::S32);
+ new_shape->size<loco::DataType::S32>(2);
+ new_shape->rank(1);
+ new_shape->dim(0) = 2;
+
+ auto batch_size = 1;
+ for (uint32_t i = 0; i < original_input->rank() - 1; ++i)
+ batch_size *= original_input->dim(i).value();
+
+ new_shape->at<loco::DataType::S32>(0) = batch_size;
+ new_shape->at<loco::DataType::S32>(1) =
+ original_input->dim(original_input->rank() - 1).value();
+ new_shape->shape_status(luci::ShapeStatus::VALID);
+
+ auto reshape = g->nodes()->create<luci::CircleReshape>();
+ reshape->tensor(original_input);
+ reshape->shape(new_shape);
+
+ bcq_input = reshape;
+ batch_rank = original_input->rank() - 2;
+ }
+
+ // If x_w formation, we should insert Transpose in front and back of BCQFullyConnected
+ if (do_w_x(weights))
+ {
+ const auto binary_hidden_size =
+ loco::must_cast<luci::CircleNode *>(fully_connected->input())
+ ->dim(batch_rank)
+ .value();
+ bcq_fc->weights_hidden_size(binary_hidden_size);
+ bcq_fc->input(bcq_input);
+ loco::replace(fully_connected).with(bcq_fc);
+ }
+ else
+ {
+ const auto binary_hidden_size =
+ loco::must_cast<luci::CircleNode *>(fully_connected->input())
+ ->dim(1 + batch_rank)
+ .value();
+ bcq_fc->weights_hidden_size(binary_hidden_size);
+
+ auto perm = g->nodes()->create<luci::CircleConst>();
+ perm->dtype(loco::DataType::S32);
+ perm->size<loco::DataType::S32>(2);
+ perm->rank(1);
+ perm->dim(0) = 2;
+ perm->at<loco::DataType::S32>(0) = 1;
+ perm->at<loco::DataType::S32>(1) = 0;
+ perm->shape_status(luci::ShapeStatus::VALID);
+
+ auto input_transpose = g->nodes()->create<luci::CircleTranspose>();
+ input_transpose->a(bcq_input);
+ input_transpose->perm(perm);
+
+ bcq_fc->input(input_transpose);
+
+ auto output_transpose = g->nodes()->create<luci::CircleTranspose>();
+ output_transpose->a(bcq_fc);
+ output_transpose->perm(perm);
+
+ loco::replace(fully_connected).with(output_transpose);
+ }
+
+ changed = true;
+ }
+ }
+ }
+
+ if (changed)
+ clear_BCQ_nodes();
+
+ return changed;
+ }
+
+private:
void add_BCQ_info_node(luci::CircleConst *node)
{
const auto node_name = node->name();
@@ -119,16 +300,65 @@ public:
return has_info;
}
+ /**
+ * @brief Exclude BCQ information nodes which are used for fusing BCQ operations
+ * from graph output by using CircleOutputExclude
+ */
+ void clear_BCQ_nodes()
+ {
+ auto clear_nodes = [](std::map<std::string, luci::CircleConst *> &nodes) {
+ for (auto &n : nodes)
+ {
+ auto node = n.second;
+
+ for (auto s : loco::succs(node))
+ {
+ if (auto outnode = dynamic_cast<luci::CircleOutput *>(s))
+ {
+ outnode->from(createNoOp(node));
+ }
+ else if (auto reshape_node = dynamic_cast<luci::CircleReshape *>(s))
+ {
+ for (auto o : loco::succs(reshape_node))
+ {
+ auto circle_output = loco::must_cast<luci::CircleOutput *>(o);
+ circle_output->from(createNoOp(reshape_node));
+ }
+ }
+ }
+ }
+ };
+
+ clear_nodes(_do_w_x);
+ clear_nodes(_alpha);
+ clear_nodes(_packed_binary_code);
+ clear_nodes(_number_of_clusters);
+ clear_nodes(_size_of_clusters);
+ clear_nodes(_qbits_of_clusters);
+ clear_nodes(_dequant_weight);
+ }
+
+ bool is_bcqinfo_valid()
+ {
+ // do_w_x should be int32 or bool type
+ for (auto n : _do_w_x)
+ {
+ if (n.second->dtype() != loco::DataType::BOOL && n.second->dtype() != loco::DataType::S32)
+ return false;
+ }
+
+ return true;
+ }
+
+private:
bool do_w_x(luci::CircleConst *node)
{
const auto prefix = node_name_prefix(node->name());
if (_do_w_x[prefix]->dtype() == loco::DataType::S32)
return _do_w_x[prefix]->at<loco::DataType::S32>(0) == 1;
- else if (_do_w_x[prefix]->dtype() == loco::DataType::BOOL)
- return _do_w_x[prefix]->at<loco::DataType::BOOL>(0);
else
- throw std::runtime_error("do_w_x should be int or bool");
+ return _do_w_x[prefix]->at<loco::DataType::BOOL>(0);
}
luci::CircleConst *get_alpha(luci::CircleConst *node)
@@ -187,64 +417,6 @@ public:
return packed_clusters;
}
- /**
- * @brief Exclude BCQ information nodes which are used for fusing BCQ operations
- * from graph output by using CircleOutputExclude
- */
- void clear_BCQ_nodes()
- {
- auto createNoOp = [](luci::CircleNode *circle_node) {
- auto graph = circle_node->graph();
- auto noOp = graph->nodes()->create<luci::CircleOutputExclude>();
-
- if (circle_node->shape_status() == luci::ShapeStatus::VALID)
- {
- noOp->dtype(circle_node->dtype());
- noOp->rank(circle_node->rank());
- for (uint32_t i = 0; i < circle_node->rank(); ++i)
- noOp->dim(i) = circle_node->dim(i);
- }
- else
- {
- // For type inference
- noOp->dtype(loco::DataType::FLOAT32);
- }
-
- return noOp;
- };
-
- auto clear_nodes = [createNoOp](std::map<std::string, luci::CircleConst *> &nodes) {
- for (auto &n : nodes)
- {
- auto node = n.second;
-
- for (auto s : loco::succs(node))
- {
- if (auto outnode = dynamic_cast<luci::CircleOutput *>(s))
- {
- outnode->from(createNoOp(node));
- }
- else if (auto reshape_node = dynamic_cast<luci::CircleReshape *>(s))
- {
- for (auto o : loco::succs(reshape_node))
- {
- auto circle_output = loco::must_cast<luci::CircleOutput *>(o);
- circle_output->from(createNoOp(reshape_node));
- }
- }
- }
- }
- };
-
- clear_nodes(_do_w_x);
- clear_nodes(_alpha);
- clear_nodes(_packed_binary_code);
- clear_nodes(_number_of_clusters);
- clear_nodes(_size_of_clusters);
- clear_nodes(_qbits_of_clusters);
- clear_nodes(_dequant_weight);
- }
-
private:
std::map<std::string, luci::CircleConst *> _do_w_x;
std::map<std::string, luci::CircleConst *> _alpha;
@@ -262,143 +434,42 @@ namespace luci
bool FuseBCQPass::run(loco::Graph *g)
{
- BCQConverter converter;
-
bool changed = false;
+ // Find BCQ version information and check validity.
+ luci::CircleConst *version_node = nullptr;
for (auto node : loco::all_nodes(g))
{
if (auto circle_const = dynamic_cast<luci::CircleConst *>(node))
{
- converter.add_BCQ_info_node(circle_const);
- }
- }
-
- for (auto node : loco::active_nodes(loco::output_nodes(g)))
- {
- if (auto gather = dynamic_cast<luci::CircleGather *>(node))
- {
- auto params = dynamic_cast<luci::CircleConst *>(gather->params());
- if (params != nullptr && converter.has_BCQ_info(params))
+ if (circle_const->name().find("/bcqinfo_version") != std::string::npos)
{
- auto bcq_gather = g->nodes()->create<luci::CircleBCQGather>();
-
- bcq_gather->input_scales(converter.get_alpha(params));
- bcq_gather->input_binary(converter.get_packed_binary_code(params));
- bcq_gather->indices(gather->indices());
- bcq_gather->input_clusters(converter.packed_clusters(params));
-
- const auto binary_hidden_size =
- loco::must_cast<luci::CircleConst *>(bcq_gather->input_binary())->dim(1).value() * 32;
- bcq_gather->input_hidden_size(binary_hidden_size);
-
- if (converter.do_w_x(params))
- {
- bcq_gather->axis(gather->axis());
- }
- else
+ // There should be only one bcqinfo_version in the model
+ if (version_node != nullptr)
{
- const auto axis_transpose = (gather->axis() == 0) ? 1 : 0;
- bcq_gather->axis(axis_transpose);
+ assert(false && "Multiple version information found");
+ return false;
}
- loco::replace(gather).with(bcq_gather);
-
- changed = true;
+ version_node = circle_const;
}
}
- else if (auto fully_connected = dynamic_cast<luci::CircleFullyConnected *>(node))
- {
- auto weights = dynamic_cast<luci::CircleConst *>(fully_connected->weights());
- if (weights != nullptr && converter.has_BCQ_info(weights))
- {
- auto bcq_fc = g->nodes()->create<luci::CircleBCQFullyConnected>();
-
- bcq_fc->weights_scales(converter.get_alpha(weights));
- bcq_fc->weights_binary(converter.get_packed_binary_code(weights));
- bcq_fc->bias(fully_connected->bias());
- bcq_fc->weights_clusters(converter.packed_clusters(weights));
- bcq_fc->fusedActivationFunction(fully_connected->fusedActivationFunction());
-
- loco::Node *bcq_input = fully_connected->input();
- int32_t batch_rank = 0;
+ }
- // If input of BCQFullyConnected has more than rank 2, we should reshape it as rank 2
- const auto original_input = loco::must_cast<luci::CircleNode *>(fully_connected->input());
- if (original_input->shape_status() == ShapeStatus::VALID && original_input->rank() > 2)
- {
- auto new_shape = g->nodes()->create<luci::CircleConst>();
- new_shape->dtype(loco::DataType::S32);
- new_shape->size<loco::DataType::S32>(2);
- new_shape->rank(1);
- new_shape->dim(0) = 2;
-
- auto batch_size = 1;
- for (uint32_t i = 0; i < original_input->rank() - 1; ++i)
- batch_size *= original_input->dim(i).value();
-
- new_shape->at<loco::DataType::S32>(0) = batch_size;
- new_shape->at<loco::DataType::S32>(1) =
- original_input->dim(original_input->rank() - 1).value();
- new_shape->shape_status(ShapeStatus::VALID);
-
- auto reshape = g->nodes()->create<luci::CircleReshape>();
- reshape->tensor(original_input);
- reshape->shape(new_shape);
-
- bcq_input = reshape;
- batch_rank = original_input->rank() - 2;
- }
+ // If version node is not found, regard it as version 1.
+ int32_t bcq_version = (version_node != nullptr) ? version_node->at<loco::DataType::S32>(0) : 1;
- // If x_w formation, we should insert Transpose in front and back of BCQFullyConnected
- if (converter.do_w_x(weights))
- {
- const auto binary_hidden_size =
- loco::must_cast<luci::CircleNode *>(fully_connected->input())
- ->dim(batch_rank)
- .value();
- bcq_fc->weights_hidden_size(binary_hidden_size);
- bcq_fc->input(bcq_input);
- loco::replace(fully_connected).with(bcq_fc);
- }
- else
- {
- const auto binary_hidden_size =
- loco::must_cast<luci::CircleNode *>(fully_connected->input())
- ->dim(1 + batch_rank)
- .value();
- bcq_fc->weights_hidden_size(binary_hidden_size);
-
- auto perm = g->nodes()->create<luci::CircleConst>();
- perm->dtype(loco::DataType::S32);
- perm->size<loco::DataType::S32>(2);
- perm->rank(1);
- perm->dim(0) = 2;
- perm->at<loco::DataType::S32>(0) = 1;
- perm->at<loco::DataType::S32>(1) = 0;
- perm->shape_status(ShapeStatus::VALID);
-
- auto input_transpose = g->nodes()->create<luci::CircleTranspose>();
- input_transpose->a(bcq_input);
- input_transpose->perm(perm);
-
- bcq_fc->input(input_transpose);
-
- auto output_transpose = g->nodes()->create<luci::CircleTranspose>();
- output_transpose->a(bcq_fc);
- output_transpose->perm(perm);
-
- loco::replace(fully_connected).with(output_transpose);
- }
+ if (bcq_version == 1)
+ changed = BCQFuser<1>().fuseBCQ(g);
+ else
+ assert(false && "Not supported BCQ version");
- changed = true;
- }
- }
+ if (changed && version_node != nullptr)
+ {
+ // If BCQ is applied and version node was found, remove the node.
+ loco::replace(version_node).with(createNoOp(version_node));
}
- if (changed)
- converter.clear_BCQ_nodes();
-
return changed;
}
diff --git a/compiler/luci/pass/src/QuantizationUtils.cpp b/compiler/luci/pass/src/QuantizationUtils.cpp
index 6726ce746..e18690605 100644
--- a/compiler/luci/pass/src/QuantizationUtils.cpp
+++ b/compiler/luci/pass/src/QuantizationUtils.cpp
@@ -24,6 +24,13 @@
namespace luci
{
+uint8_t fp32_to_uint8_cast(float f)
+{
+ assert(std::numeric_limits<uint8_t>::min() <= f);
+ assert(f <= std::numeric_limits<uint8_t>::max());
+ return static_cast<uint8_t>(f);
+}
+
void compute_sym_scale_zp(float min, float max, float &scaling_factor, int64_t &zp,
float &nudged_min, float &nudged_max)
{
@@ -78,7 +85,7 @@ void compute_asym_scale_zp(float min, float max, float &scaling_factor, int64_t
}
else
zero_point_double = qmin_double - rmin / scale;
- if (zero_point_double <= qmin_double)
+ if (min >= 0)
{
assert(min >= 0 && max >= 0);
nudged_zero_point = kMinScale;
@@ -86,7 +93,7 @@ void compute_asym_scale_zp(float min, float max, float &scaling_factor, int64_t
if (min > 0 && max > 0)
WARN(l) << "The minimum and maximum values are all positive." << std::endl;
}
- else if (zero_point_double >= qmax_double)
+ else if (max < 0)
{
assert(min < 0 && max < 0);
nudged_zero_point = kMaxScale;
@@ -96,7 +103,14 @@ void compute_asym_scale_zp(float min, float max, float &scaling_factor, int64_t
else
{
assert(min < 0 && max >= 0);
- nudged_zero_point = static_cast<uint8_t>(std::round(zero_point_double));
+ nudged_zero_point = fp32_to_uint8_cast(std::round(zero_point_double));
+ }
+
+ // protect scale from being very low due to overflow
+ if (scale < 1e-5)
+ {
+ scale = 1e-5;
+ nudged_zero_point = fp32_to_uint8_cast(std::round(qmin_double - rmin / scale));
}
nudged_min = static_cast<float>((qmin_double - nudged_zero_point) * scale);
diff --git a/compiler/luci/pass/src/QuantizeWithMinMaxPass.cpp b/compiler/luci/pass/src/QuantizeWithMinMaxPass.cpp
index f8abee751..b335a53b4 100644
--- a/compiler/luci/pass/src/QuantizeWithMinMaxPass.cpp
+++ b/compiler/luci/pass/src/QuantizeWithMinMaxPass.cpp
@@ -138,7 +138,8 @@ bool is_quantized(const CircleNode *node)
node->dtype() == loco::DataType::S32; // bias
}
-void sym_wquant_per_channel(CircleConst *node, std::vector<float> &scaling_factor)
+void sym_wquant_per_channel(CircleConst *node, std::vector<float> &scaling_factor,
+ int32_t &channel_dim_index)
{
assert(node->dtype() == loco::DataType::FLOAT32);
@@ -153,7 +154,6 @@ void sym_wquant_per_channel(CircleConst *node, std::vector<float> &scaling_facto
uint32_t indices[4] = {
0,
};
- int channel_dim_index{0};
if (!get_channel_dim_index(node, dimension, channel_dim_index))
{
@@ -189,7 +189,7 @@ void sym_wquant_per_channel(CircleConst *node, std::vector<float> &scaling_facto
}
void asym_wquant_per_channel(CircleConst *node, std::vector<float> &min,
- std::vector<float> &scaling_factor)
+ std::vector<float> &scaling_factor, int32_t &channel_dim_index)
{
assert(node->dtype() == loco::DataType::FLOAT32);
@@ -204,7 +204,6 @@ void asym_wquant_per_channel(CircleConst *node, std::vector<float> &min,
uint32_t indices[4] = {
0,
};
- int channel_dim_index{0};
if (!get_channel_dim_index(node, dimension, channel_dim_index))
{
@@ -282,6 +281,10 @@ bool is_weights(CircleNode *node)
if (dw_conv != nullptr && dw_conv->filter() == circle_const)
return true;
+ auto t_conv = dynamic_cast<CircleTransposeConv *>(out);
+ if (t_conv != nullptr && t_conv->filter() == circle_const && circle_const->rank() == 4)
+ return true;
+
auto fc = dynamic_cast<CircleFullyConnected *>(out);
if (fc != nullptr && fc->weights() == circle_const)
return true;
@@ -350,8 +353,8 @@ struct QuantizeActivation final : public luci::CircleNodeMutableVisitor<bool>
circle_node->dtype(loco::DataType::S16);
}
- circle_node->quantparam()->max[0] = nudged_max;
- circle_node->quantparam()->min[0] = nudged_min;
+ circle_node->quantparam()->min.clear();
+ circle_node->quantparam()->max.clear();
circle_node->quantparam()->scale.push_back(scaling_factor);
circle_node->quantparam()->zerop.push_back(zp);
}
@@ -472,15 +475,19 @@ struct QuantizeWeights final : public luci::CircleNodeMutableVisitor<bool>
assert(quantparam != nullptr);
auto min = quantparam->min;
auto scaling_factor = quantparam->scale;
+ int32_t channel_dim_index = 0;
if (output_type == loco::DataType::U8)
{
- asym_wquant_per_channel(circle_const, min, scaling_factor);
+ asym_wquant_per_channel(circle_const, min, scaling_factor, channel_dim_index);
}
else
{
- sym_wquant_per_channel(circle_const, scaling_factor);
+ sym_wquant_per_channel(circle_const, scaling_factor, channel_dim_index);
}
+ quantparam->min.clear();
+ quantparam->max.clear();
+ quantparam->quantized_dimension = channel_dim_index;
}
// Find min/max per layer-wise
else
@@ -493,6 +500,8 @@ struct QuantizeWeights final : public luci::CircleNodeMutableVisitor<bool>
auto min = quantparam->min[0];
auto scaling_factor = quantparam->scale[0];
asym_wquant_per_layer(circle_const, min, scaling_factor);
+ quantparam->min.clear();
+ quantparam->max.clear();
}
}
}
diff --git a/compiler/luci/service/src/CircleShapeInferenceRule.cpp b/compiler/luci/service/src/CircleShapeInferenceRule.cpp
index a291cfe70..6355ec546 100644
--- a/compiler/luci/service/src/CircleShapeInferenceRule.cpp
+++ b/compiler/luci/service/src/CircleShapeInferenceRule.cpp
@@ -1010,6 +1010,12 @@ public:
loco::NodeShape visit(const luci::CircleNeg *node) final { return use_x(node); }
+ loco::NodeShape visit(const luci::CircleNonMaxSuppressionV4 *node) final
+ {
+ const auto boxes_shape = loco::shape_get(node->boxes()).as<loco::TensorShape>();
+ return loco::NodeShape{boxes_shape};
+ }
+
loco::NodeShape visit(const luci::CircleNotEqual *node) final { return broadcast_xy(node); }
loco::NodeShape visit(const luci::CircleOneHot *node) final
@@ -1818,6 +1824,18 @@ public:
return output_shape;
}
+ loco::NodeShape visit(const luci::CircleUnique *node) final
+ {
+ auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>();
+
+ assert(input_shape.rank() == 1);
+
+ loco::TensorShape shape_output;
+ shape_output = own_shape(node);
+
+ return loco::NodeShape{shape_output};
+ }
+
loco::NodeShape visit(const luci::CircleTransposeConv *node) final
{
// TransposeConv's output shape is written in its 'inputSizes' argument
@@ -2019,6 +2037,34 @@ public:
return loco::NodeShape{*then_graph_output->shape()};
}
+ loco::NodeShape visit(const luci::CircleNonMaxSuppressionV4Out *node) final
+ {
+ const loco::DataType S32 = loco::DataType::S32;
+
+ auto nmsv4 = dynamic_cast<const luci::CircleNonMaxSuppressionV4 *>(node->input());
+ if (nmsv4 == nullptr)
+ INTERNAL_EXN("CircleNonMaxSuppressionV4 IR is not configured correctly");
+
+ auto index = node->index();
+ if (index == 1)
+ return loco::TensorShape({0});
+
+ assert(index == 0);
+
+ auto unknown = loco::TensorShape{loco::Dimension()};
+ auto max_output_size = dynamic_cast<const luci::CircleConst *>(nmsv4->max_output_size());
+ if (max_output_size == nullptr)
+ return unknown; // we need CircleConst for max output size
+
+ LUCI_ASSERT(max_output_size->dtype() == S32, "Only support int32 for max_output_size");
+
+ if (max_output_size->size<S32>() < 1)
+ return unknown;
+
+ auto max_output_size_value = uint32_t(max_output_size->at<S32>(0));
+ return loco::TensorShape{max_output_size_value};
+ }
+
loco::NodeShape visit(const luci::CircleSplitOut *node) final
{
const loco::DataType S32 = loco::DataType::S32;
@@ -2142,6 +2188,19 @@ public:
return loco::NodeShape{output_shape};
}
+ loco::NodeShape visit(const luci::CircleUniqueOut *node) final
+ {
+ auto unique = dynamic_cast<const luci::CircleUnique *>(node->input());
+ if (unique == nullptr)
+ {
+ INTERNAL_EXN("CircleUnique IR is not configured correctly");
+ }
+
+ auto unique_shape = loco::shape_get(unique).as<loco::TensorShape>();
+
+ return loco::NodeShape{unique_shape};
+ }
+
loco::NodeShape visit(const luci::CircleUnpackOut *node) final
{
auto unpack = dynamic_cast<const luci::CircleUnpack *>(node->input());
diff --git a/compiler/luci/service/src/CircleTypeInferenceRule.cpp b/compiler/luci/service/src/CircleTypeInferenceRule.cpp
index de2ba3ea4..e7910bfc0 100644
--- a/compiler/luci/service/src/CircleTypeInferenceRule.cpp
+++ b/compiler/luci/service/src/CircleTypeInferenceRule.cpp
@@ -252,6 +252,11 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT
loco::DataType visit(const luci::CircleNeg *node) final { return loco::dtype_get(node->x()); }
+ loco::DataType visit(const luci::CircleNonMaxSuppressionV4 *node) final
+ {
+ return loco::dtype_get(node->boxes());
+ }
+
loco::DataType visit(const luci::CircleNotEqual *) final { return loco::DataType::BOOL; }
loco::DataType visit(const luci::CirclePack *node) final
@@ -345,7 +350,10 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT
return loco::dtype_get(node->tensor());
}
- loco::DataType visit(const luci::CircleResizeBilinear *) final { return loco::DataType::FLOAT32; }
+ loco::DataType visit(const luci::CircleResizeBilinear *node) final
+ {
+ return loco::dtype_get(node->input());
+ }
loco::DataType visit(const luci::CircleResizeNearestNeighbor *node) final
{
@@ -472,6 +480,11 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT
return loco::dtype_get(node->outBackprop());
}
+ loco::DataType visit(const luci::CircleUnique *node) final
+ {
+ return loco::dtype_get(node->input());
+ }
+
loco::DataType visit(const luci::CircleUnpack *node) final
{
return loco::dtype_get(node->value());
@@ -569,6 +582,13 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT
return then_graph_output->dtype();
}
+ loco::DataType visit(const luci::CircleNonMaxSuppressionV4Out *node) final
+ {
+ (void)node;
+ assert(node->index() == 0 || node->index() == 1);
+ return loco::DataType::S32;
+ }
+
loco::DataType visit(const luci::CircleSplitOut *node) final
{
return loco::dtype_get(node->input());
@@ -589,6 +609,17 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT
return loco::DataType::S32;
}
+ loco::DataType visit(const luci::CircleUniqueOut *node) final
+ {
+ if (node->index() == 0)
+ {
+ return loco::dtype_get(node->input());
+ }
+ assert(node->index() == 1);
+ auto unique = loco::must_cast<luci::CircleUnique *>(node->input());
+ return unique->idx_out_type();
+ }
+
loco::DataType visit(const luci::CircleUnpackOut *node) final
{
return loco::dtype_get(node->input());
diff --git a/compiler/luci/tests/test.lst b/compiler/luci/tests/test.lst
index 188e29828..9fd42ed4e 100644
--- a/compiler/luci/tests/test.lst
+++ b/compiler/luci/tests/test.lst
@@ -20,6 +20,7 @@ addread(ArgMin_U8_001)
addread(ArgMin_U8_002)
addread(ArgMin_U8_003)
addread(AveragePool2D_000)
+addread(AveragePool2D_U8_000)
addread(BatchMatMul_000)
addread(BatchMatMulV2_000)
addread(BatchMatMulV2_001)
@@ -30,13 +31,16 @@ addread(Ceil_000)
addread(Concatenation_000)
addread(Concatenation_U8_000)
addread(Conv2D_000)
+addread(Conv2D_001)
addread(Conv2D_002)
addread(Conv2D_003)
addread(Conv2D_U8_000)
+addread(Conv2D_U8_001)
addread(Cos_000)
addread(DepthToSpace_000)
addread(DepthwiseConv2D_000)
addread(DepthwiseConv2D_U8_000)
+addread(DepthwiseConv2D_U8_001)
addread(DepthwiseConv2D_001)
addread(Div_000)
addread(ELU_000)
@@ -64,6 +68,7 @@ addread(GreaterEqual_000)
addread(If_000)
addread(If_001)
addread(L2Normalize_000)
+addread(L2Normalize_U8_000)
addread(L2Pool2D_000)
addread(L2Pool2D_U8_000)
addread(LeakyRelu_000)
@@ -75,6 +80,7 @@ addread(LogicalAnd_000)
addread(LogicalNot_000)
addread(LogicalOr_000)
addread(Logistic_000)
+addread(Logistic_U8_000)
addread(LogSoftmax_000)
addread(MatMul_000)
addread(MatrixDiag_000)
@@ -84,6 +90,7 @@ addread(MaxPool2D_000)
addread(MaxPool2D_U8_000)
addread(Mean_000)
addread(Mean_001)
+addread(Mean_U8_000)
addread(Minimum_000)
addread(MirrorPad_000)
addread(Mul_000)
@@ -97,6 +104,7 @@ addread(OneHot_003)
addread(Pack_000)
addread(Pack_U8_000)
addread(Pad_000)
+addread(Pad_U8_000)
addread(Pow_000)
addread(PRelu_000)
addread(Range_000)
@@ -212,6 +220,7 @@ addwrite(ArgMin_U8_001)
addwrite(ArgMin_U8_002)
addwrite(ArgMin_U8_003)
addwrite(AveragePool2D_000)
+addwrite(AveragePool2D_U8_000)
addwrite(BatchMatMul_000)
addwrite(BatchMatMulV2_000)
addwrite(BatchMatMulV2_001)
@@ -222,13 +231,16 @@ addwrite(Ceil_000)
addwrite(Concatenation_000)
addwrite(Concatenation_U8_000)
addwrite(Conv2D_000)
+addwrite(Conv2D_001)
addwrite(Conv2D_002)
addwrite(Conv2D_003)
addwrite(Conv2D_U8_000)
+addwrite(Conv2D_U8_001)
addwrite(Cos_000)
addwrite(DepthToSpace_000)
addwrite(DepthwiseConv2D_000)
addwrite(DepthwiseConv2D_U8_000)
+addwrite(DepthwiseConv2D_U8_001)
addwrite(DepthwiseConv2D_001)
addwrite(Div_000)
addwrite(ELU_000)
@@ -256,6 +268,7 @@ addwrite(GreaterEqual_000)
addwrite(If_000)
addwrite(If_001)
addwrite(L2Normalize_000)
+addwrite(L2Normalize_U8_000)
addwrite(L2Pool2D_000)
addwrite(L2Pool2D_U8_000)
addwrite(LeakyRelu_000)
@@ -267,6 +280,7 @@ addwrite(LogicalAnd_000)
addwrite(LogicalNot_000)
addwrite(LogicalOr_000)
addwrite(Logistic_000)
+addwrite(Logistic_U8_000)
addwrite(LogSoftmax_000)
addwrite(MatMul_000)
addwrite(MatrixDiag_000)
@@ -276,6 +290,7 @@ addwrite(MaxPool2D_000)
addwrite(MaxPool2D_U8_000)
addwrite(Mean_000)
addwrite(Mean_001)
+addwrite(Mean_U8_000)
addwrite(Minimum_000)
addwrite(MirrorPad_000)
addwrite(Mul_000)
diff --git a/compiler/mio-tflite/CMakeLists.txt b/compiler/mio-tflite/CMakeLists.txt
index 2cfed1449..9ef2859b9 100644
--- a/compiler/mio-tflite/CMakeLists.txt
+++ b/compiler/mio-tflite/CMakeLists.txt
@@ -5,11 +5,7 @@ if(NOT FlatBuffers_FOUND)
return()
endif(NOT FlatBuffers_FOUND)
-# TODO recover official release version
-# NOTE we cannot use version number like "2.3.0-rc0" for find_package()
-# use TensorFlowSource-2.3.0-rc0 as config itself
-# nnas_find_package(TensorFlowSource EXACT 2.3.0 QUIET)
-nnas_find_package(TensorFlowSource-2.3.0-rc0 QUIET)
+nnas_find_package(TensorFlowSource EXACT 2.3.0 QUIET)
if(NOT TensorFlowSource_FOUND)
return()
diff --git a/compiler/one-cmds/CMakeLists.txt b/compiler/one-cmds/CMakeLists.txt
index 7d73d9b23..173b8b476 100644
--- a/compiler/one-cmds/CMakeLists.txt
+++ b/compiler/one-cmds/CMakeLists.txt
@@ -1,5 +1,6 @@
set(ONE_COMMAND_FILES
one-import
+ one-import-bcq
one-import-tf
one-import-tflite
one-optimize
@@ -26,7 +27,7 @@ foreach(ONE_COMMAND IN ITEMS ${ONE_COMMAND_FILES})
install(FILES ${ONE_COMMAND}
PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE
- GROUP_READ GROUP_WRITE GROUP_EXECUTE
+ GROUP_READ GROUP_EXECUTE
WORLD_READ WORLD_EXECUTE
DESTINATION bin)
diff --git a/compiler/one-cmds/how-to-prepare-virtualenv.txt b/compiler/one-cmds/how-to-prepare-virtualenv.txt
index 41fff3aaf..62a94968b 100644
--- a/compiler/one-cmds/how-to-prepare-virtualenv.txt
+++ b/compiler/one-cmds/how-to-prepare-virtualenv.txt
@@ -1,12 +1,12 @@
About
-----
-Last update: 2020-07-14
+Last update: 2020-08-03
This document explains about 'one-prepare-venv' command.
'one-prepare-venv' will prepare python3 virtual environment with tensorflow-cpu
-version 2.3.0rc0, recommanded 2.x version as of now, so that 'one-import-tf'
+version 2.3.0, recommanded 2.x version as of now, so that 'one-import-tf'
command can execute properly.
diff --git a/compiler/one-cmds/how-to-use-one-commands.txt b/compiler/one-cmds/how-to-use-one-commands.txt
index 6c2176afa..0ee69e077 100644
--- a/compiler/one-cmds/how-to-use-one-commands.txt
+++ b/compiler/one-cmds/how-to-use-one-commands.txt
@@ -1,7 +1,7 @@
About
-----
-Last update: 2020-07-14
+Last update: 2020-07-31
This document briefly explains how to use one-* commands.
Detailed options are not explained here. Run the command to see options.
@@ -30,6 +30,27 @@ Syntax: one-import [framework] [options]
Currently supported frameworks are 'tf', 'tflite' for TensorFlow and TensorFlow
lite.
+one-import-bcq
+-------------
+
+This will convert Tensorflow model file (.pb) to our circle model file with applying BCQ.
+To execute this command, original Tensorflow model file must include BCQ information.
+
+This command invokes following scripts internally.
+- preserve_bcq_info : Prevent BCQ information vanishing problem
+- generate_bcq_info : Designate BCQ information nodes as model output automatically
+- tf2tfliteV2 : Convert Tensorflow model to tflite model
+- tflite2circle : Convert Tensorflow Lite model to circle model
+When this command is finished, BCQ information nodes will be removed if BCQ information
+was valid and applying BCQ is done correctly without any errors.
+
+As tf2tfliteV2.py runs TensorFlow lite converter, you need to have TensorFlow
+installed in your system. We recommand to use 2.3.0 for now.
+
+We provide python virtual environment and one-import-bcq will enter and leave
+this environment so that you don't need to explictly 'activate' virtual
+environment.
+
one-import-tf
-------------
@@ -40,7 +61,7 @@ will internally use TensorFlow lite converter and then invoke tflite2circle
converter to convert tflite model to circle model.
As tf2tfliteV2.py runs TensorFlow lite converter, you need to have TensorFlow
-installed in your system. We recommand to use 2.3.0rc0 for now.
+installed in your system. We recommand to use 2.3.0 for now.
We provide python virtual environment and one-import-tf will enter and leave
this environment so that you don't need to explictly 'activate' virtual
diff --git a/compiler/one-cmds/one-codegen b/compiler/one-cmds/one-codegen
index 2c80664e2..820b6d8a3 100644
--- a/compiler/one-cmds/one-codegen
+++ b/compiler/one-cmds/one-codegen
@@ -18,7 +18,7 @@ DRIVER_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
function Usage()
{
- echo "Usage: $0 [BACKEND] ..."
+ echo "Usage: one-codegen [BACKEND] ..."
echo "Available BACKEND drivers:"
backend_exist=0
for file in `find $DRIVER_PATH -name *-compile -type f`;
@@ -33,23 +33,34 @@ function Usage()
if [ $backend_exist == 0 ]; then
echo " (There is no available backend drivers)"
fi
+
+ exit 255
}
-# Get command from command-line
-BACKEND=$1; shift
-BACKEND_DRIVER="$BACKEND-compile"
+function version()
+{
+ $DRIVER_PATH/one-version one-codegen
+ exit 255
+}
-if [[ -z "${BACKEND_DRIVER}" ]]; then
+# Get command from command-line
+BACKEND=$1
+if [[ -z ${BACKEND} ]]; then
Usage
- exit 255
fi
+shift
+
+if [[ "${BACKEND}" == "--version" ]]; then
+ version
+fi
+
+BACKEND_DRIVER="${BACKEND}-compile"
BACKEND_DRIVER_CMD="${DRIVER_PATH}/${BACKEND_DRIVER}"
if [[ ! -f "${BACKEND_DRIVER_CMD}" ]]; then
echo "ERROR: '${BACKEND_DRIVER}' is not supported"
Usage
- exit 255
fi
"${BACKEND_DRIVER_CMD}" "$@"
diff --git a/compiler/one-cmds/one-import b/compiler/one-cmds/one-import
index dbf4af534..b1dd8f4c3 100644
--- a/compiler/one-cmds/one-import
+++ b/compiler/one-cmds/one-import
@@ -18,7 +18,7 @@ DRIVER_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
function Usage()
{
- echo "Usage: $0 [FRAMEWORK] ..."
+ echo "Usage: one-import [FRAMEWORK] ..."
echo "Available FRAMEWORK drivers:"
framework_exist=0
for file in "$DRIVER_PATH"/one-import-*;
@@ -31,23 +31,34 @@ function Usage()
if [ $framework_exist == 0 ]; then
echo " (There is no available import drivers)"
fi
+
+ exit 255
}
-# Get command from command-line
-FRAMEWORK=$1; shift
-FRAMEWORK_DRIVER="one-import-$FRAMEWORK"
+function version()
+{
+ $DRIVER_PATH/one-version one-import-tf
+ exit 255
+}
-if [[ -z "${FRAMEWORK_DRIVER}" ]]; then
+# Get command from command-line
+FRAMEWORK=$1
+if [[ -z ${FRAMEWORK} ]]; then
Usage
- exit 255
+fi
+shift
+
+if [ ${FRAMEWORK} = "--version" ]; then
+ version
fi
+FRAMEWORK_DRIVER="one-import-$FRAMEWORK"
+
FRAMEWORK_DRIVER_CMD="${DRIVER_PATH}/${FRAMEWORK_DRIVER}"
if [[ ! -f "${FRAMEWORK_DRIVER_CMD}" ]]; then
echo "ERROR: '${FRAMEWORK_DRIVER}' is not supported"
Usage
- exit 255
fi
"${FRAMEWORK_DRIVER_CMD}" "$@"
diff --git a/compiler/one-cmds/one-import-bcq b/compiler/one-cmds/one-import-bcq
new file mode 100644
index 000000000..98dd1efed
--- /dev/null
+++ b/compiler/one-cmds/one-import-bcq
@@ -0,0 +1,150 @@
+#!/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.
+
+set -e
+
+DRIVER_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+
+usage()
+{
+ echo "Convert TensorFlow model with BCQ to circle."
+ echo "Usage: one-import-bcq"
+ echo " --version Show version information and exit"
+ echo " --input_path <path/to/tfmodel/with/BCQ>"
+ echo " --output_path <path/to/circle>"
+ echo " --input_arrays <names of the input arrays, comma-separated>"
+ echo " --input_shapes <input shapes, colon-separated>"
+ echo " --output_arrays <names of the output arrays, comma-separated>"
+ echo " --v2 Use TensorFlow 2.x interface (default is 1.x interface)"
+ exit 255
+}
+
+version()
+{
+ $DRIVER_PATH/one-version one-import-bcq
+ exit 255
+}
+
+TF_INTERFACE="--v1"
+
+# Parse command-line arguments
+#
+while [ "$#" -ne 0 ]; do
+ CUR="$1"
+
+ case $CUR in
+ '--help')
+ usage
+ ;;
+ '--version')
+ version
+ ;;
+ '--input_path')
+ export INPUT_PATH="$2"
+ shift 2
+ ;;
+ '--output_path')
+ export OUTPUT_PATH="$2"
+ shift 2
+ ;;
+ '--input_arrays')
+ export INPUT_ARRAYS="$2"
+ shift 2
+ ;;
+ '--input_shapes')
+ export INPUT_SHAPES="$2"
+ shift 2
+ ;;
+ '--output_arrays')
+ export OUTPUT_ARRAYS="$2"
+ shift 2
+ ;;
+ '--v2')
+ TF_INTERFACE="--v2"
+ shift
+ ;;
+ *)
+ echo "Unknown parameter: ${CUR}"
+ shift
+ ;;
+ esac
+done
+
+if [ -z ${INPUT_PATH} ] || [ ! -e ${INPUT_PATH} ]; then
+ echo "Error: input model not found"
+ echo ""
+ usage
+ exit 2
+fi
+
+FILE_BASE=$(basename ${OUTPUT_PATH})
+MODEL_NAME="${FILE_BASE%.*}"
+
+TMPDIR=$(mktemp -d)
+trap "{ rm -rf $TMPDIR; }" EXIT
+
+# activate python virtual environment
+VIRTUALENV_LINUX="${DRIVER_PATH}/venv/bin/activate"
+VIRTUALENV_WINDOWS="${DRIVER_PATH}/venv/Scripts/activate"
+
+if [ -e ${VIRTUALENV_LINUX} ]; then
+ source ${VIRTUALENV_LINUX}
+elif [ -e ${VIRTUALENV_WINDOWS} ]; then
+ source ${VIRTUALENV_WINDOWS}
+fi
+
+# remove previous log
+rm -rf "${OUTPUT_PATH}.log"
+
+# generate temporary preserved pb file
+echo "${DRIVER_PATH}/preserve_bcq_info" --input_path ${INPUT_PATH} \
+--output_path "${TMPDIR}/${MODEL_NAME}_preserved.pb" > "${OUTPUT_PATH}.log"
+echo " " >> "${OUTPUT_PATH}.log"
+
+"${DRIVER_PATH}/preserve_bcq_info" --input_path ${INPUT_PATH} \
+--output_path "${TMPDIR}/${MODEL_NAME}_preserved.pb" >> "${OUTPUT_PATH}.log" 2>&1
+
+# generate output_arrays automatically
+echo "${DRIVER_PATH}/generate_bcq_output_arrays" \
+--input_path "${TMPDIR}/${MODEL_NAME}_preserved.pb" \
+--output_path "${TMPDIR}/${MODEL_NAME}_output_arrays.txt" > "${OUTPUT_PATH}.log"
+echo " " >> "${OUTPUT_PATH}.log"
+
+"${DRIVER_PATH}/generate_bcq_output_arrays" \
+--input_path "${TMPDIR}/${MODEL_NAME}_preserved.pb" \
+--output_path "${TMPDIR}/${MODEL_NAME}_output_arrays.txt" >> "${OUTPUT_PATH}.log" 2>&1
+
+# generate temporary tflite file
+CONVERT_SCRIPT="python ${DRIVER_PATH}/tf2tfliteV2.py ${TF_INTERFACE} "
+CONVERT_SCRIPT+="--input_path ${TMPDIR}/${MODEL_NAME}_preserved.pb "
+CONVERT_SCRIPT+="--input_arrays ${INPUT_ARRAYS} "
+CONVERT_SCRIPT+="--output_path ${TMPDIR}/${MODEL_NAME}.tflite "
+CONVERT_SCRIPT+="--output_arrays ${OUTPUT_ARRAYS}$(cat ${TMPDIR}/${MODEL_NAME}_output_arrays.txt) "
+if [ ! -z ${INPUT_SHAPES} ]; then
+ CONVERT_SCRIPT+="--input_shapes ${INPUT_SHAPES} "
+fi
+
+echo ${CONVERT_SCRIPT} > "${OUTPUT_PATH}.log"
+$CONVERT_SCRIPT >> "${OUTPUT_PATH}.log" 2>&1
+
+# convert .tflite to .circle
+echo " " >> "${OUTPUT_PATH}.log"
+echo "${DRIVER_PATH}/tflite2circle" "${TMPDIR}/${MODEL_NAME}.tflite" \
+"${OUTPUT_PATH}" >> "${OUTPUT_PATH}.log"
+echo " " >> "${OUTPUT_PATH}.log"
+
+"${DRIVER_PATH}/tflite2circle" "${TMPDIR}/${MODEL_NAME}.tflite" \
+"${OUTPUT_PATH}" >> "${OUTPUT_PATH}.log" 2>&1
diff --git a/compiler/one-cmds/one-import-tf b/compiler/one-cmds/one-import-tf
index c048a4e0c..d59e1c529 100644
--- a/compiler/one-cmds/one-import-tf
+++ b/compiler/one-cmds/one-import-tf
@@ -22,14 +22,24 @@ usage()
{
echo "Convert TensorFlow model to circle."
echo "Usage: one-import-tf"
+ echo " --version Show version information and exit"
echo " --input_path <path/to/tfmodel>"
echo " --output_path <path/to/circle>"
echo " --input_arrays <names of the input arrays, comma-separated>"
echo " --input_shapes <input shapes, colon-separated>"
echo " --output_arrays <names of the output arrays, comma-separated>"
- exit 0
+ echo " --v2 Use TensorFlow 2.x interface (default is 1.x interface)"
+ exit 255
}
+version()
+{
+ $DRIVER_PATH/one-version one-import-tf
+ exit 255
+}
+
+TF_INTERFACE="--v1"
+
# Parse command-line arguments
#
while [ "$#" -ne 0 ]; do
@@ -39,6 +49,9 @@ while [ "$#" -ne 0 ]; do
'--help')
usage
;;
+ '--version')
+ version
+ ;;
'--input_path')
export INPUT_PATH="$2"
shift 2
@@ -59,6 +72,10 @@ while [ "$#" -ne 0 ]; do
export OUTPUT_ARRAYS="$2"
shift 2
;;
+ '--v2')
+ TF_INTERFACE="--v2"
+ shift
+ ;;
*)
echo "Unknown parameter: ${CUR}"
shift
@@ -92,14 +109,21 @@ fi
# remove previous log
rm -rf "${OUTPUT_PATH}.log"
+show_err_onexit()
+{
+ cat "${OUTPUT_PATH}.log"
+}
+
+trap show_err_onexit ERR
+
# generate temporary tflite file
-echo "python" "${DRIVER_PATH}/tf2tfliteV2.py" --v2 --input_path ${INPUT_PATH} \
+echo "python" "${DRIVER_PATH}/tf2tfliteV2.py" ${TF_INTERFACE} --input_path ${INPUT_PATH} \
--input_arrays ${INPUT_ARRAYS} --input_shapes ${INPUT_SHAPES} \
--output_path "${TMPDIR}/${MODEL_NAME}.tflite" \
--output_arrays ${OUTPUT_ARRAYS} > "${OUTPUT_PATH}.log"
echo " " >> "${OUTPUT_PATH}.log"
-python "${DRIVER_PATH}/tf2tfliteV2.py" --v2 --input_path ${INPUT_PATH} \
+python "${DRIVER_PATH}/tf2tfliteV2.py" ${TF_INTERFACE} --input_path ${INPUT_PATH} \
--input_arrays ${INPUT_ARRAYS} --input_shapes ${INPUT_SHAPES} \
--output_path "${TMPDIR}/${MODEL_NAME}.tflite" \
--output_arrays ${OUTPUT_ARRAYS} >> "${OUTPUT_PATH}.log" 2>&1
diff --git a/compiler/one-cmds/one-import-tflite b/compiler/one-cmds/one-import-tflite
index 31ed5af85..053489c92 100644
--- a/compiler/one-cmds/one-import-tflite
+++ b/compiler/one-cmds/one-import-tflite
@@ -22,9 +22,16 @@ usage()
{
echo "Convert TensorFlow lite model to circle."
echo "Usage: one-import-tflite"
+ echo " --version Show version information and exit"
echo " --input_path <path/to/tflitemodel>"
echo " --output_path <path/to/circle>"
- exit 0
+ exit 255
+}
+
+version()
+{
+ $DRIVER_PATH/one-version one-import-tflite
+ exit 255
}
# Parse command-line arguments
@@ -36,6 +43,9 @@ while [ "$#" -ne 0 ]; do
'--help')
usage
;;
+ '--version')
+ version
+ ;;
'--input_path')
export INPUT_PATH="$2"
shift 2
@@ -55,12 +65,18 @@ if [ -z ${INPUT_PATH} ] || [ ! -e ${INPUT_PATH} ]; then
echo "Error: input model not found"
echo ""
usage
- exit 2
fi
# remove previous log
rm -rf "${OUTPUT_PATH}.log"
+show_err_onexit()
+{
+ cat "${OUTPUT_PATH}.log"
+}
+
+trap show_err_onexit ERR
+
# convert .tflite to .circle
echo "${DRIVER_PATH}/tflite2circle" "${INPUT_PATH}" "${OUTPUT_PATH}" > "${OUTPUT_PATH}.log"
diff --git a/compiler/one-cmds/one-optimize b/compiler/one-cmds/one-optimize
index 95384c10d..17b6b980e 100644
--- a/compiler/one-cmds/one-optimize
+++ b/compiler/one-cmds/one-optimize
@@ -22,6 +22,7 @@ usage()
{
echo "Optimize circle model."
echo "Usage: one-optimize"
+ echo " --version Show version information and exit"
echo " --all Enable all optimization algorithms"
echo " --fuse_bcq Enable FuseBCQ Pass"
echo " --fuse_instnorm Enable FuseInstanceNormalization Pass"
@@ -33,7 +34,13 @@ usage()
echo " Enable ResolveCustomOpMatMulPass Pass"
echo " --input_path <path/to/input/circle>"
echo " --output_path <path/to/output/circle>"
- exit 0
+ exit 255
+}
+
+version()
+{
+ $DRIVER_PATH/one-version one-optimize
+ exit 255
}
OPTIMIZE_all=0
@@ -52,6 +59,9 @@ while [ "$#" -ne 0 ]; do
'--help')
usage
;;
+ '--version')
+ version
+ ;;
'--all')
OPTIMIZE_all=1
shift
@@ -96,7 +106,6 @@ if [ -z ${INPUT_PATH} ] || [ ! -e ${INPUT_PATH} ]; then
echo "Error: input model not found"
echo ""
usage
- exit 2
fi
OPTIMIZE_OPTIONS=""
@@ -123,6 +132,13 @@ fi
# remove previous log
rm -rf "${OUTPUT_PATH}.log"
+show_err_onexit()
+{
+ cat "${OUTPUT_PATH}.log"
+}
+
+trap show_err_onexit ERR
+
# NOTE do not wrap ${OPTIMIZE_OPTIONS} with ""
# optimize circle
echo "${DRIVER_PATH}/circle2circle" ${OPTIMIZE_OPTIONS} \
diff --git a/compiler/one-cmds/one-pack b/compiler/one-cmds/one-pack
index 2bc4c601d..023b0a85f 100644
--- a/compiler/one-cmds/one-pack
+++ b/compiler/one-cmds/one-pack
@@ -22,9 +22,16 @@ usage()
{
echo "Package circle to nnpkg"
echo "Usage: one-pack"
+ echo " -v, --version Show version information and exit"
echo " -i <path/to/circle>"
echo " -o <path/to/nnpackage/folder>"
- exit 0
+ exit 255
+}
+
+version()
+{
+ $DRIVER_PATH/one-version one-pack
+ exit 255
}
# Parse command-line arguments
@@ -36,6 +43,12 @@ while [ "$#" -ne 0 ]; do
'--help')
usage
;;
+ '-v')
+ version
+ ;;
+ '--version')
+ version
+ ;;
'-i')
export INPUT_PATH="$2"
shift 2
@@ -55,13 +68,22 @@ if [ -z ${INPUT_PATH} ] || [ ! -e ${INPUT_PATH} ]; then
echo "Error: input model not found"
echo ""
usage
- exit 2
fi
+INPUT_FILE=$(basename "${INPUT_PATH}")
+LOG_FILE="${INPUT_FILE%.*}.pack.log"
+
# remove previous log
-rm -rf "${OUTPUT_PATH}.log"
+rm -rf "${LOG_FILE}"
+
+show_err_onexit()
+{
+ cat "${LOG_FILE}"
+}
+
+trap show_err_onexit ERR
# Package circle model file to nnpkg
-echo "${DRIVER_PATH}/model2nnpkg.sh" -o "${OUTPUT_PATH}" "${INPUT_PATH}" > "${OUTPUT_PATH}.log"
+echo "${DRIVER_PATH}/model2nnpkg.sh" -o "${OUTPUT_PATH}" "${INPUT_PATH}" > "${LOG_FILE}"
-"${DRIVER_PATH}/model2nnpkg.sh" -o "${OUTPUT_PATH}" "${INPUT_PATH}" >> "${OUTPUT_PATH}.log" 2>&1
+"${DRIVER_PATH}/model2nnpkg.sh" -o "${OUTPUT_PATH}" "${INPUT_PATH}" >> "${LOG_FILE}" 2>&1
diff --git a/compiler/one-cmds/one-prepare-venv b/compiler/one-cmds/one-prepare-venv
index fce838d81..0a53bd3dd 100644
--- a/compiler/one-cmds/one-prepare-venv
+++ b/compiler/one-cmds/one-prepare-venv
@@ -26,7 +26,19 @@ if [ -f ${VENV_ACTIVATE} ]; then
fi
# Install prerequisites
-python3 -m pip install -U virtualenv
+python3 -m pip install --user -U virtualenv
+
+function error_no_ensurepip ()
+{
+ echo "ERROR: python3 'ensurepip' module is not found."
+ echo " On ubuntu, try following command:"
+ echo
+ echo " apt install python$(python3 --version | awk '{print $2}' | awk -F. '{print $1"."$2}')-venv"
+ echo
+ echo " You may need root privilege for this."
+ exit 1
+}
+python3 -m ensurepip --version > /dev/null 2>&1 || error_no_ensurepip
# Create python virtual enviornment
python3 -m venv "${DRIVER_PATH}/venv"
@@ -37,4 +49,4 @@ source "${VENV_ACTIVATE}"
python -m pip --default-timeout=1000 --trusted-host pypi.org --trusted-host files.pythonhost.org \
install -U pip setuptools
python -m pip --default-timeout=1000 --trusted-host pypi.org --trusted-host files.pythonhost.org \
- install tensorflow-cpu==2.3.0rc0
+ install tensorflow-cpu==2.3.0
diff --git a/compiler/one-cmds/one-quantize b/compiler/one-cmds/one-quantize
index ff9e26672..c74b2c2d2 100644
--- a/compiler/one-cmds/one-quantize
+++ b/compiler/one-cmds/one-quantize
@@ -22,16 +22,23 @@ usage()
{
echo "Quantize circle model."
echo "Usage: one-quantize"
+ echo " --version Show version information and exit"
echo " --input_dtype Input data type (supported: float32, default=float32)"
echo " --quantized_dtype Output quantized data type (supported: uint8, default=uint8)"
- echo " --granularity Quantize granularity (supported: layer, default=layer)"
+ echo " --granularity Quantize granularity (supported: layer, channel, default=layer)"
echo " --min_percentile Minimum percentile (0.0~100.0, default=1.0)"
echo " --max_percentile Maximum percentile (0.0~100.0, default=99.0)"
echo " --mode Record mode (supported: percentile/moving_average, default=percentile)"
echo " --input_path <path/to/input/circle>"
echo " --input_data <path/to/input/data>"
echo " --output_path <path/to/output/circle>"
- exit 0
+ exit 255
+}
+
+version()
+{
+ $DRIVER_PATH/one-version one-quantize
+ exit 255
}
INPUT_DTYPE=float32
@@ -50,6 +57,9 @@ while [ "$#" -ne 0 ]; do
'--help')
usage
;;
+ '--version')
+ version
+ ;;
'--input_dtype')
INPUT_DTYPE="$2"
@@ -100,13 +110,11 @@ if [ -z ${INPUT_PATH} ] || [ ! -e ${INPUT_PATH} ]; then
echo "Error: input model not found"
echo ""
usage
- exit 2
fi
if [ -z ${INPUT_DATA} ] || [ ! -e ${INPUT_DATA} ]; then
echo "Error: input data not found"
echo ""
usage
- exit 2
fi
FILE_BASE=$(basename ${OUTPUT_PATH})
@@ -118,6 +126,13 @@ trap "{ rm -rf $TMPDIR; }" EXIT
# remove previous log
rm -rf "${OUTPUT_PATH}.log"
+show_err_onexit()
+{
+ cat "${OUTPUT_PATH}.log"
+}
+
+trap show_err_onexit ERR
+
# quantize circle
echo "${DRIVER_PATH}/circle-quantizer" \
--quantize_dequantize_weights ${INPUT_DTYPE} ${QUANTIZED_DTYPE} ${GRANULARITY} \
diff --git a/compiler/one-cmds/requires.cmake b/compiler/one-cmds/requires.cmake
index 9b858ad90..50c24579f 100644
--- a/compiler/one-cmds/requires.cmake
+++ b/compiler/one-cmds/requires.cmake
@@ -3,3 +3,5 @@ require("tflite2circle")
require("circle2circle")
require("circle-quantizer")
require("record-minmax")
+require("vconone")
+require("bcq-tools")
diff --git a/compiler/pota-quantization-value-test/CMakeLists.txt b/compiler/pota-quantization-value-test/CMakeLists.txt
index d97ffc123..73b9ead73 100644
--- a/compiler/pota-quantization-value-test/CMakeLists.txt
+++ b/compiler/pota-quantization-value-test/CMakeLists.txt
@@ -49,21 +49,21 @@ add_test(
${QUANTIZATION_VALUE_TEST_WITH_PARAM}
)
-#add_test(
-# NAME pota_record_minmax_test
-# COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/test_record_minmax.sh"
-# "${TEST_CONFIG}"
-# "${ARTIFACTS_BIN_PATH}"
-# ${QUANTIZATION_VALUE_TEST_WITH_PARAM}
-#)
+add_test(
+ NAME pota_record_minmax_test
+ COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/test_record_minmax.sh"
+ "${TEST_CONFIG}"
+ "${ARTIFACTS_BIN_PATH}"
+ ${QUANTIZATION_VALUE_TEST_WITH_PARAM}
+)
-#add_test(
-# NAME pota_quantization_test
-# COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/test_quantization.sh"
-# "${TEST_CONFIG}"
-# "${ARTIFACTS_BIN_PATH}"
-# ${QUANTIZATION_VALUE_TEST_WITH_PARAM}
-#)
+add_test(
+ NAME pota_quantization_test
+ COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/test_quantization.sh"
+ "${TEST_CONFIG}"
+ "${ARTIFACTS_BIN_PATH}"
+ ${QUANTIZATION_VALUE_TEST_WITH_PARAM}
+)
-#set_tests_properties(pota_record_minmax_test PROPERTIES DEPENDS pota_fake_wquant_test)
-#set_tests_properties(pota_quantization_test PROPERTIES DEPENDS pota_record_minmax_test)
+set_tests_properties(pota_record_minmax_test PROPERTIES DEPENDS pota_fake_wquant_test)
+set_tests_properties(pota_quantization_test PROPERTIES DEPENDS pota_record_minmax_test)
diff --git a/compiler/pota-quantization-value-test/compare_tensors.py b/compiler/pota-quantization-value-test/compare_tensors.py
index 258d46dc9..7d95d182d 100755
--- a/compiler/pota-quantization-value-test/compare_tensors.py
+++ b/compiler/pota-quantization-value-test/compare_tensors.py
@@ -69,7 +69,7 @@ def compare_quantization(tensor, tensor_name, expect_dir):
if key == "weights":
expected_weights = np.array(json_load["weights"])
input_weights = tensor["weights"][:]
- if np.allclose(input_weights, expected_weights, rtol=0, atol=0) == False:
+ if np.allclose(input_weights, expected_weights, rtol=0, atol=1) == False:
print("Quantized weights of " + tensor_name + " (" + str(input_weights) +
") do not match with expected value (" + str(expected_weights) +
").")
@@ -87,7 +87,7 @@ def compare_quantization(tensor, tensor_name, expect_dir):
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=0) == False:
+ 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) + ").")
diff --git a/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/fake_quantization/ker.json b/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/fake_quantization/ker.json
index 21b8ecad7..2558bb2be 100644
--- a/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/fake_quantization/ker.json
+++ b/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/fake_quantization/ker.json
@@ -3,44 +3,44 @@
[
[
[
- 1.003921627998352,
- 2.007843255996704
- ],
+ 1.0039215087890625,
+ 2.007843017578125
+ ],
[
- -3.0117647647857666,
+ -3.0117650032043457,
-4.015686511993408
]
- ],
+ ],
[
[
- -5.019608020782471,
- 6.023529529571533
- ],
+ -5.019608497619629,
+ 6.023530006408691
+ ],
[
- -7.027451038360596,
- 7.968627452850342
+ -7.027451515197754,
+ 7.9686279296875
]
]
- ],
+ ],
[
[
[
- 4.015686511993408,
- -2.007843255996704
- ],
+ 4.01568603515625,
+ -2.007843494415283
+ ],
[
- 3.0117647647857666,
- -1.003921627998352
+ 3.0117645263671875,
+ -1.0039215087890625
]
- ],
+ ],
[
[
- -7.968627452850342,
- -6.023529529571533
- ],
+ -7.9686279296875,
+ -6.023530006408691
+ ],
[
- 7.027451038360596,
- 5.019608020782471
+ 7.027451515197754,
+ 5.019608497619629
]
]
]
diff --git a/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/quantization/bias.json b/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/quantization/bias.json
index 462d0d3e3..50d44ece7 100644
--- a/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/quantization/bias.json
+++ b/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/quantization/bias.json
@@ -1,7 +1,7 @@
- {
- "scale": 0.0059054209919261825,
- "weights": [
- 169.0,
- 339.0
- ]
- }
+{
+ "weights": [
+ 4069,
+ 8138
+ ],
+ "scale": 0.0002457468386200985
+}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/quantization/ifm.json b/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/quantization/ifm.json
index 107117b80..24508860d 100644
--- a/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/quantization/ifm.json
+++ b/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/quantization/ifm.json
@@ -1,4 +1,4 @@
{
- "scale": 0.09411764705882353,
+ "scale": 0.003916590008884668,
"zero_point": 0.0
}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/quantization/ker.json b/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/quantization/ker.json
index 3a6e171a1..b249a0ce5 100644
--- a/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/quantization/ker.json
+++ b/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/quantization/ker.json
@@ -1,52 +1,52 @@
{
- "max": 7.968627450980392,
- "scale": 0.06274509803921569,
"weights": [
[
[
[
- 144,
- 160
- ],
+ 143,
+ 159
+ ],
[
- 80,
- 64
+ 79,
+ 63
]
- ],
+ ],
[
[
- 48,
- 224
- ],
+ 47,
+ 223
+ ],
[
- 16,
- 255
+ 15,
+ 254
]
]
- ],
+ ],
[
[
[
- 192,
- 96
- ],
+ 191,
+ 95
+ ],
[
- 176,
- 112
+ 175,
+ 111
]
- ],
+ ],
[
[
- 1,
- 32
- ],
+ 0,
+ 31
+ ],
[
- 240,
- 208
+ 239,
+ 207
]
]
]
- ],
- "min": -8.031372549019608,
- "zero_point": 128.0
+ ],
+ "scale": 0.062745101749897,
+ "zero_point": 127.0,
+ "min": -7.9686279296875,
+ "max": 8.031373023986816
}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/quantization/ofm.json b/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/quantization/ofm.json
index 2374639b1..a2dd6681f 100644
--- a/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/quantization/ofm.json
+++ b/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/quantization/ofm.json
@@ -1,4 +1,4 @@
{
- "scale": 0.17836222929113052,
+ "scale": 0.037479765713214874,
"zero_point": 0.0
}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/record_minmax/ifm.json b/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/record_minmax/ifm.json
index 563c0424f..42f8b5617 100644
--- a/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/record_minmax/ifm.json
+++ b/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/record_minmax/ifm.json
@@ -1,4 +1,4 @@
{
- "max": 24.0,
- "min": 1.0
+ "min": 0.005472412034869194,
+ "max": 0.9987304735183716
}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/record_minmax/ofm.json b/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/record_minmax/ofm.json
index fd0c6dc86..1862e8cb2 100644
--- a/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/record_minmax/ofm.json
+++ b/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/layer/uint8/record_minmax/ofm.json
@@ -1,4 +1,4 @@
{
- "max": 45.48236846923828,
- "min": 0.0
+ "min": 0.0,
+ "max": 9.557340850830078
}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/fake_quantization/ker.json b/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/fake_quantization/ker.json
index 11e91ca42..cd3479781 100644
--- a/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/fake_quantization/ker.json
+++ b/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/fake_quantization/ker.json
@@ -3,29 +3,29 @@
[
[
[
- 0.9725490212440491,
- 1.9450980424880981,
- 3.0392158031463623,
+ 0.9725494384765625,
+ 1.945098876953125,
+ 3.039216995239258,
4.0117645263671875
- ],
+ ],
[
- -8.996078491210938,
- 9.968626976013184,
- -10.941176414489746,
- 12.035294532775879
+ -8.996077537536621,
+ 9.9686279296875,
+ -10.94117546081543,
+ 12.035295486450195
]
- ],
+ ],
[
[
- 4.984313488006592,
- 5.956862926483154,
- 7.050980567932129,
- 8.023529052734375
- ],
+ 4.98431396484375,
+ 5.9568634033203125,
+ 7.050981521606445,
+ 8.023530960083008
+ ],
[
- 13.007843017578125,
- -13.980392456054688,
- 14.952940940856934,
+ 13.007843017578125,
+ -13.980391502380371,
+ 14.95294189453125,
-16.04705810546875
]
]
diff --git a/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/quantization/bias.json b/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/quantization/bias.json
index df7cb14c4..e60ff312e 100644
--- a/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/quantization/bias.json
+++ b/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/quantization/bias.json
@@ -1,9 +1,9 @@
{
- "scale": 0.007627835447904652,
"weights": [
- 131.0,
- 262.0,
- 393.0,
- 524.0
- ]
+ 2156,
+ 4312,
+ 6468,
+ 8624
+ ],
+ "scale": 0.0004638272181067826
}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/quantization/ifm.json b/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/quantization/ifm.json
index 254ce899a..4ec4ef2d7 100644
--- a/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/quantization/ifm.json
+++ b/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/quantization/ifm.json
@@ -1,4 +1,4 @@
{
- "scale": 0.06274509803921569,
+ "scale": 0.0038153529167175293,
"zero_point": 0.0
}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/quantization/ker.json b/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/quantization/ker.json
index 3d14da173..01835fbde 100644
--- a/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/quantization/ker.json
+++ b/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/quantization/ker.json
@@ -1,38 +1,38 @@
{
- "max": 14.952941176470588,
- "scale": 0.12156862745098039,
"weights": [
[
[
[
- 140,
- 148,
- 157,
+ 140,
+ 148,
+ 157,
165
- ],
+ ],
[
- 58,
- 214,
- 42,
+ 58,
+ 214,
+ 42,
231
]
- ],
+ ],
[
[
- 173,
- 181,
- 190,
+ 173,
+ 181,
+ 190,
198
- ],
+ ],
[
- 239,
- 17,
- 255,
+ 239,
+ 17,
+ 255,
0
]
]
]
- ],
- "min": -16.04705882352941,
- "zero_point": 132.0
+ ],
+ "scale": 0.12156862765550613,
+ "zero_point": 132.0,
+ "min": -16.04705810546875,
+ "max": 14.952940940856934
}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/quantization/ofm.json b/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/quantization/ofm.json
index 85dd4d9ae..39c64f3ef 100644
--- a/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/quantization/ofm.json
+++ b/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/quantization/ofm.json
@@ -1,4 +1,4 @@
{
- "scale": 0.893733185412837,
+ "scale": 0.07362665981054306,
"zero_point": 0.0
}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/record_minmax/ifm.json b/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/record_minmax/ifm.json
index 9aee7bcb0..bb4292efe 100644
--- a/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/record_minmax/ifm.json
+++ b/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/record_minmax/ifm.json
@@ -1,4 +1,4 @@
{
- "max": 16.0,
- "min": 1.0
+ "min": 0.02638142943382263,
+ "max": 0.9729149651527405
}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/record_minmax/ofm.json b/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/record_minmax/ofm.json
index aa42a6614..1c118e1db 100644
--- a/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/record_minmax/ofm.json
+++ b/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/layer/uint8/record_minmax/ofm.json
@@ -1,4 +1,4 @@
{
- "max": 227.90196228027344,
- "min": 0.0
+ "min": 0.0,
+ "max": 18.77479721069336
}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/FullyConnected_003/layer/uint8/fake_quantization/weight.json b/compiler/pota-quantization-value-test/expected_outputs/FullyConnected_003/layer/uint8/fake_quantization/weight.json
new file mode 100644
index 000000000..e1da53ab0
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/FullyConnected_003/layer/uint8/fake_quantization/weight.json
@@ -0,0 +1,76 @@
+{
+ "weights": [
+ [
+ 1.0039215087890625,
+ 2.007843017578125,
+ -3.0117650032043457,
+ -4.015686511993408,
+ -5.019608497619629,
+ 6.023530006408691,
+ -7.027451515197754,
+ 7.9686279296875,
+ 4.01568603515625,
+ -2.007843494415283,
+ 3.0117645263671875,
+ -1.0039215087890625,
+ -7.9686279296875,
+ -6.023530006408691,
+ 7.027451515197754,
+ 5.019608497619629
+ ],
+ [
+ 1.0039215087890625,
+ 2.007843017578125,
+ -3.0117650032043457,
+ -4.015686511993408,
+ -5.019608497619629,
+ 6.023530006408691,
+ -7.027451515197754,
+ 7.9686279296875,
+ 4.01568603515625,
+ -2.007843494415283,
+ 3.0117645263671875,
+ -1.0039215087890625,
+ -7.9686279296875,
+ -6.023530006408691,
+ 7.027451515197754,
+ 5.019608497619629
+ ],
+ [
+ 1.0039215087890625,
+ 2.007843017578125,
+ -3.0117650032043457,
+ -4.015686511993408,
+ -5.019608497619629,
+ 6.023530006408691,
+ -7.027451515197754,
+ 7.9686279296875,
+ 4.01568603515625,
+ -2.007843494415283,
+ 3.0117645263671875,
+ -1.0039215087890625,
+ -7.9686279296875,
+ -6.023530006408691,
+ 7.027451515197754,
+ 5.019608497619629
+ ],
+ [
+ 1.0039215087890625,
+ 2.007843017578125,
+ -3.0117650032043457,
+ -4.015686511993408,
+ -5.019608497619629,
+ 6.023530006408691,
+ -7.027451515197754,
+ 7.9686279296875,
+ 4.01568603515625,
+ -2.007843494415283,
+ 3.0117645263671875,
+ -1.0039215087890625,
+ -7.9686279296875,
+ -6.023530006408691,
+ 7.027451515197754,
+ 5.019608497619629
+ ]
+ ]
+}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/FullyConnected_003/layer/uint8/quantization/bias.json b/compiler/pota-quantization-value-test/expected_outputs/FullyConnected_003/layer/uint8/quantization/bias.json
new file mode 100644
index 000000000..ecb49bb64
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/FullyConnected_003/layer/uint8/quantization/bias.json
@@ -0,0 +1,9 @@
+{
+ "weights": [
+ 415,
+ -829,
+ -1244,
+ 1658
+ ],
+ "scale": 0.00241205753304663
+}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/FullyConnected_003/layer/uint8/quantization/in.json b/compiler/pota-quantization-value-test/expected_outputs/FullyConnected_003/layer/uint8/quantization/in.json
new file mode 100644
index 000000000..654824b5d
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/FullyConnected_003/layer/uint8/quantization/in.json
@@ -0,0 +1,4 @@
+{
+ "scale": 0.03844216465950012,
+ "zero_point": 126.0
+}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/FullyConnected_003/layer/uint8/quantization/out.json b/compiler/pota-quantization-value-test/expected_outputs/FullyConnected_003/layer/uint8/quantization/out.json
new file mode 100644
index 000000000..3baa42155
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/FullyConnected_003/layer/uint8/quantization/out.json
@@ -0,0 +1,4 @@
+{
+ "scale": 0.741962730884552,
+ "zero_point": 156.0
+}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/FullyConnected_003/layer/uint8/quantization/weight.json b/compiler/pota-quantization-value-test/expected_outputs/FullyConnected_003/layer/uint8/quantization/weight.json
new file mode 100644
index 000000000..940224049
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/FullyConnected_003/layer/uint8/quantization/weight.json
@@ -0,0 +1,80 @@
+{
+ "weights": [
+ [
+ 143,
+ 159,
+ 79,
+ 63,
+ 47,
+ 223,
+ 15,
+ 254,
+ 191,
+ 95,
+ 175,
+ 111,
+ 0,
+ 31,
+ 239,
+ 207
+ ],
+ [
+ 143,
+ 159,
+ 79,
+ 63,
+ 47,
+ 223,
+ 15,
+ 254,
+ 191,
+ 95,
+ 175,
+ 111,
+ 0,
+ 31,
+ 239,
+ 207
+ ],
+ [
+ 143,
+ 159,
+ 79,
+ 63,
+ 47,
+ 223,
+ 15,
+ 254,
+ 191,
+ 95,
+ 175,
+ 111,
+ 0,
+ 31,
+ 239,
+ 207
+ ],
+ [
+ 143,
+ 159,
+ 79,
+ 63,
+ 47,
+ 223,
+ 15,
+ 254,
+ 191,
+ 95,
+ 175,
+ 111,
+ 0,
+ 31,
+ 239,
+ 207
+ ]
+ ],
+ "scale": 0.062745101749897,
+ "zero_point": 127.0,
+ "min": -7.9686279296875,
+ "max": 8.031373023986816
+}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/FullyConnected_003/layer/uint8/record_minmax/in.json b/compiler/pota-quantization-value-test/expected_outputs/FullyConnected_003/layer/uint8/record_minmax/in.json
new file mode 100644
index 000000000..a8ec5b2b6
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/FullyConnected_003/layer/uint8/record_minmax/in.json
@@ -0,0 +1,4 @@
+{
+ "min": -4.832756385803223,
+ "max": 4.969995346069336
+}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/FullyConnected_003/layer/uint8/record_minmax/out.json b/compiler/pota-quantization-value-test/expected_outputs/FullyConnected_003/layer/uint8/record_minmax/out.json
new file mode 100644
index 000000000..de3b41564
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/FullyConnected_003/layer/uint8/record_minmax/out.json
@@ -0,0 +1,4 @@
+{
+ "min": -115.99438369750976,
+ "max": 73.20612327575684
+}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/TransposeConv_001/layer/uint8/fake_quantization/ker.json b/compiler/pota-quantization-value-test/expected_outputs/TransposeConv_001/layer/uint8/fake_quantization/ker.json
new file mode 100644
index 000000000..76a0440a0
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/TransposeConv_001/layer/uint8/fake_quantization/ker.json
@@ -0,0 +1,48 @@
+{
+ "weights": [
+ [
+ [
+ [
+ 0.960784912109375,
+ 2.0588245391845703
+ ],
+ [
+ -3.0196075439453125,
+ -3.980391502380371
+ ],
+ [
+ 4.9411773681640625,
+ -6.039215087890625
+ ]
+ ],
+ [
+ [
+ 7.0,
+ 7.960784912109375
+ ],
+ [
+ -9.058823585510254,
+ -10.019607543945312
+ ],
+ [
+ 10.980392456054688,
+ -11.941176414489746
+ ]
+ ],
+ [
+ [
+ 13.039216995239258,
+ 14.000001907348633
+ ],
+ [
+ -14.960784912109375,
+ -16.05882453918457
+ ],
+ [
+ 17.019607543945312,
+ -17.980392456054688
+ ]
+ ]
+ ]
+ ]
+}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/TransposeConv_001/layer/uint8/quantization/ifm.json b/compiler/pota-quantization-value-test/expected_outputs/TransposeConv_001/layer/uint8/quantization/ifm.json
new file mode 100644
index 000000000..dc5ca8dd5
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/TransposeConv_001/layer/uint8/quantization/ifm.json
@@ -0,0 +1,4 @@
+{
+ "scale": 0.03869570419192314,
+ "zero_point": 126.0
+}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/TransposeConv_001/layer/uint8/quantization/ker.json b/compiler/pota-quantization-value-test/expected_outputs/TransposeConv_001/layer/uint8/quantization/ker.json
new file mode 100644
index 000000000..bc150bbb0
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/TransposeConv_001/layer/uint8/quantization/ker.json
@@ -0,0 +1,52 @@
+{
+ "weights": [
+ [
+ [
+ [
+ 138,
+ 146
+ ],
+ [
+ 109,
+ 102
+ ],
+ [
+ 167,
+ 87
+ ]
+ ],
+ [
+ [
+ 182,
+ 189
+ ],
+ [
+ 65,
+ 58
+ ],
+ [
+ 211,
+ 44
+ ]
+ ],
+ [
+ [
+ 226,
+ 233
+ ],
+ [
+ 22,
+ 14
+ ],
+ [
+ 255,
+ 0
+ ]
+ ]
+ ]
+ ],
+ "scale": 0.13725490868091583,
+ "zero_point": 131.0,
+ "min": -17.980392456054688,
+ "max": 17.019609451293945
+}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/TransposeConv_001/layer/uint8/quantization/ofm.json b/compiler/pota-quantization-value-test/expected_outputs/TransposeConv_001/layer/uint8/quantization/ofm.json
new file mode 100644
index 000000000..bfd862189
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/TransposeConv_001/layer/uint8/quantization/ofm.json
@@ -0,0 +1,4 @@
+{
+ "scale": 1.6333034038543701,
+ "zero_point": 127.0
+}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/TransposeConv_001/layer/uint8/record_minmax/ifm.json b/compiler/pota-quantization-value-test/expected_outputs/TransposeConv_001/layer/uint8/record_minmax/ifm.json
new file mode 100644
index 000000000..2d2af08a6
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/TransposeConv_001/layer/uint8/record_minmax/ifm.json
@@ -0,0 +1,4 @@
+{
+ "min": -4.890846576690674,
+ "max": 4.976558513641357
+}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/TransposeConv_001/layer/uint8/record_minmax/ofm.json b/compiler/pota-quantization-value-test/expected_outputs/TransposeConv_001/layer/uint8/record_minmax/ofm.json
new file mode 100644
index 000000000..24598f06e
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/TransposeConv_001/layer/uint8/record_minmax/ofm.json
@@ -0,0 +1,4 @@
+{
+ "min": -207.54233032226563,
+ "max": 208.95002136230468
+}
diff --git a/compiler/pota-quantization-value-test/test.lst b/compiler/pota-quantization-value-test/test.lst
index 65613ff8f..9eb348922 100644
--- a/compiler/pota-quantization-value-test/test.lst
+++ b/compiler/pota-quantization-value-test/test.lst
@@ -1,2 +1,4 @@
addTest(Conv2D_004 layer uint8)
addTest(DepthwiseConv2D_002 layer uint8)
+addTest(FullyConnected_003 layer uint8)
+addTest(TransposeConv_001 layer uint8)
diff --git a/compiler/pota-quantization-value-test/test_inputs/Conv2D_004/layer/uint8/0.txt b/compiler/pota-quantization-value-test/test_inputs/Conv2D_004/layer/uint8/0.txt
index 8803cb178..0614b5e83 100644
--- a/compiler/pota-quantization-value-test/test_inputs/Conv2D_004/layer/uint8/0.txt
+++ b/compiler/pota-quantization-value-test/test_inputs/Conv2D_004/layer/uint8/0.txt
@@ -1 +1 @@
-1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
+0.01090685,0.0581577 ,0.637094 ,0.64067715,0.26264507,0.13692169,0.9649414 ,0.5117181 ,0.18012471,0.07855253,0.6358017 ,0.62257963,0.41469443,0.93169045,0.20763828,0.7634293 ,0.75929826,0.72708374,0.23463063,0.58222896,0.6351517 ,0.68781173,0.5558012 ,0.7652179
diff --git a/compiler/pota-quantization-value-test/test_inputs/Conv2D_004/layer/uint8/1.txt b/compiler/pota-quantization-value-test/test_inputs/Conv2D_004/layer/uint8/1.txt
new file mode 100644
index 000000000..b1c39382f
--- /dev/null
+++ b/compiler/pota-quantization-value-test/test_inputs/Conv2D_004/layer/uint8/1.txt
@@ -0,0 +1 @@
+0.57017624,0.08235867,0.03672464,0.40372616,0.7353964 ,0.59611887,0.7675548 ,0.21004233,0.09803218,0.20009473,0.8821493 ,0.17015271,0.14840214,0.99910176,0.37003204,0.22893582,0.43173164,0.3105084 ,0.41997132,0.43714985,0.08115962,0.71896386,0.7810953 ,0.00524598
diff --git a/compiler/pota-quantization-value-test/test_inputs/Conv2D_004/layer/uint8/2.txt b/compiler/pota-quantization-value-test/test_inputs/Conv2D_004/layer/uint8/2.txt
new file mode 100644
index 000000000..7e562de75
--- /dev/null
+++ b/compiler/pota-quantization-value-test/test_inputs/Conv2D_004/layer/uint8/2.txt
@@ -0,0 +1 @@
+0.65292275,0.79842275,0.97853714,0.6711518 ,0.607567 ,0.40971732,0.74838483,0.95853555,0.32158023,0.911524 ,0.66938365,0.8573132 ,0.3047727 ,0.5561248 ,0.914098 ,0.07650814,0.37868017,0.29269257,0.19652605,0.63025194,0.61496884,0.32011527,0.8204132 ,0.21866946
diff --git a/compiler/pota-quantization-value-test/test_inputs/Conv2D_004/layer/uint8/3.txt b/compiler/pota-quantization-value-test/test_inputs/Conv2D_004/layer/uint8/3.txt
new file mode 100644
index 000000000..2958a7f54
--- /dev/null
+++ b/compiler/pota-quantization-value-test/test_inputs/Conv2D_004/layer/uint8/3.txt
@@ -0,0 +1 @@
+0.4548901 ,0.56957537,0.0252368 ,0.4884317 ,0.7516498 ,0.02631272,0.22107519,0.95249426,0.34902394,0.11520014,0.808911 ,0.4148615 ,0.63615656,0.84020686,0.3633697 ,0.23993976,0.54176176,0.86938345,0.81628686,0.6380988 ,0.91891205,0.0406627 ,0.90289026,0.9429013
diff --git a/compiler/pota-quantization-value-test/test_inputs/Conv2D_004/layer/uint8/4.txt b/compiler/pota-quantization-value-test/test_inputs/Conv2D_004/layer/uint8/4.txt
new file mode 100644
index 000000000..fc969308e
--- /dev/null
+++ b/compiler/pota-quantization-value-test/test_inputs/Conv2D_004/layer/uint8/4.txt
@@ -0,0 +1 @@
+0.9309136 ,0.02123719,0.64467335,0.6910113 ,0.47402772,0.54622203,0.31527275,0.81530565,0.98981965,0.36102158,0.03114039,0.1902339 ,0.45183742,0.60178596,0.4683102 ,0.59810966,0.40558222,0.5420302 ,0.72699505,0.9575108 ,0.46746576,0.08518691,0.40302262,0.69213694
diff --git a/compiler/pota-quantization-value-test/test_inputs/DepthwiseConv2D_002/layer/uint8/0.txt b/compiler/pota-quantization-value-test/test_inputs/DepthwiseConv2D_002/layer/uint8/0.txt
index c210774d2..44f0ff107 100644
--- a/compiler/pota-quantization-value-test/test_inputs/DepthwiseConv2D_002/layer/uint8/0.txt
+++ b/compiler/pota-quantization-value-test/test_inputs/DepthwiseConv2D_002/layer/uint8/0.txt
@@ -1 +1 @@
-1, 2, 7, 8, 3, 4, 9, 10, 5, 6, 11, 12, 13, 14, 15, 16
+0.31365377,0.6127105 ,0.7047126 ,0.2511918 ,0.16652136,0.36075932,0.44332707,0.77615815,0.60456425,0.26207635,0.28714025,0.11579613,0.89698446,0.67223394,0.3757766 ,0.11787009
diff --git a/compiler/pota-quantization-value-test/test_inputs/DepthwiseConv2D_002/layer/uint8/1.txt b/compiler/pota-quantization-value-test/test_inputs/DepthwiseConv2D_002/layer/uint8/1.txt
new file mode 100644
index 000000000..98e81041f
--- /dev/null
+++ b/compiler/pota-quantization-value-test/test_inputs/DepthwiseConv2D_002/layer/uint8/1.txt
@@ -0,0 +1 @@
+0.9409595 ,0.3991174 ,0.43546647,0.221152 ,0.7794665 ,0.8619514 ,0.5903087 ,0.24476172,0.5932698 ,0.2727837 ,0.3980262 ,0.13329633,0.4319272 ,0.37872055,0.1721639 ,0.92437047
diff --git a/compiler/pota-quantization-value-test/test_inputs/DepthwiseConv2D_002/layer/uint8/2.txt b/compiler/pota-quantization-value-test/test_inputs/DepthwiseConv2D_002/layer/uint8/2.txt
new file mode 100644
index 000000000..e9867529b
--- /dev/null
+++ b/compiler/pota-quantization-value-test/test_inputs/DepthwiseConv2D_002/layer/uint8/2.txt
@@ -0,0 +1 @@
+0.6484028 ,0.09222967,0.76285905,0.02265582,0.2564394 ,0.11219095,0.22529566,0.09101159,0.15937322,0.3540595 ,0.25971088,0.4681136 ,0.4279646 ,0.5386553 ,0.11397707,0.7413688
diff --git a/compiler/pota-quantization-value-test/test_inputs/DepthwiseConv2D_002/layer/uint8/3.txt b/compiler/pota-quantization-value-test/test_inputs/DepthwiseConv2D_002/layer/uint8/3.txt
new file mode 100644
index 000000000..9b36fb520
--- /dev/null
+++ b/compiler/pota-quantization-value-test/test_inputs/DepthwiseConv2D_002/layer/uint8/3.txt
@@ -0,0 +1 @@
+0.9182678 ,0.8253187 ,0.6572848 ,0.46436486,0.45208713,0.42112917,0.24383743,0.16039051,0.24649048,0.63431305,0.31141657,0.25664324,0.721266 ,0.18996912,0.35422477,0.8826148
diff --git a/compiler/pota-quantization-value-test/test_inputs/DepthwiseConv2D_002/layer/uint8/4.txt b/compiler/pota-quantization-value-test/test_inputs/DepthwiseConv2D_002/layer/uint8/4.txt
new file mode 100644
index 000000000..6b8957dcc
--- /dev/null
+++ b/compiler/pota-quantization-value-test/test_inputs/DepthwiseConv2D_002/layer/uint8/4.txt
@@ -0,0 +1 @@
+0.97424644,0.9360494 ,0.6849295 ,0.21313633,0.23943195,0.32497332,0.5091704 ,0.67543274,0.49667478,0.73460567,0.5866559 ,0.5312464 ,0.8252662 ,0.36093768,0.7143621 ,0.7234413
diff --git a/compiler/pota-quantization-value-test/test_inputs/FullyConnected_003/layer/uint8/0.txt b/compiler/pota-quantization-value-test/test_inputs/FullyConnected_003/layer/uint8/0.txt
new file mode 100644
index 000000000..233e5eae3
--- /dev/null
+++ b/compiler/pota-quantization-value-test/test_inputs/FullyConnected_003/layer/uint8/0.txt
@@ -0,0 +1 @@
+ 2.7731526 , 2.451602 , 3.7535272 ,-1.2774152 , 1.5482912 , 1.3402948 , 4.4792123 ,-4.4954367 , 3.354679 ,-3.3615496 ,-4.619757 ,-3.3659618 , 4.7626247 ,-1.3596478 ,-4.835548 , 0.78964525
diff --git a/compiler/pota-quantization-value-test/test_inputs/FullyConnected_003/layer/uint8/1.txt b/compiler/pota-quantization-value-test/test_inputs/FullyConnected_003/layer/uint8/1.txt
new file mode 100644
index 000000000..6a126081d
--- /dev/null
+++ b/compiler/pota-quantization-value-test/test_inputs/FullyConnected_003/layer/uint8/1.txt
@@ -0,0 +1 @@
+ 0.5400839 ,-3.2621996 ,-3.4817135 , 3.8183312 , 0.48498327, 2.9812584 , 4.111276 , 0.11223658, 4.7201405 , 2.4256718 , 1.4895477 , 4.7596602 ,-0.32709372, 1.3507305 ,-0.30043927,-1.8077502
diff --git a/compiler/pota-quantization-value-test/test_inputs/FullyConnected_003/layer/uint8/2.txt b/compiler/pota-quantization-value-test/test_inputs/FullyConnected_003/layer/uint8/2.txt
new file mode 100644
index 000000000..eccd2c625
--- /dev/null
+++ b/compiler/pota-quantization-value-test/test_inputs/FullyConnected_003/layer/uint8/2.txt
@@ -0,0 +1 @@
+ 3.8758078 , 4.978636 ,-0.22925885,-2.6760504 ,-1.9160627 ,-4.609644 ,-0.9515802 , 3.558274 , 2.9096057 , 0.3340422 , 0.38608226,-0.32168412, 4.688853 ,-4.583811 ,-2.5113506 ,-4.6688786
diff --git a/compiler/pota-quantization-value-test/test_inputs/FullyConnected_003/layer/uint8/3.txt b/compiler/pota-quantization-value-test/test_inputs/FullyConnected_003/layer/uint8/3.txt
new file mode 100644
index 000000000..0da05277c
--- /dev/null
+++ b/compiler/pota-quantization-value-test/test_inputs/FullyConnected_003/layer/uint8/3.txt
@@ -0,0 +1 @@
+-2.9868221 , 2.4237797 , 1.0833962 ,-0.9231426 ,-2.1091506 ,-2.6163697 ,-0.23101932,-1.9252896 , 4.7034135 , 3.1088963 ,-2.345823 ,-2.7866168 ,-3.186763 ,-4.431844 , 3.3113294 , 0.9501982
diff --git a/compiler/pota-quantization-value-test/test_inputs/FullyConnected_003/layer/uint8/4.txt b/compiler/pota-quantization-value-test/test_inputs/FullyConnected_003/layer/uint8/4.txt
new file mode 100644
index 000000000..ace24f7c1
--- /dev/null
+++ b/compiler/pota-quantization-value-test/test_inputs/FullyConnected_003/layer/uint8/4.txt
@@ -0,0 +1 @@
+ 3.9716747 ,-2.254871 , 1.1943274 ,-2.212602 , 3.4311683 , 1.114989 , 4.0739036 , 0.47244295,-3.5793104 ,-3.359908 ,-4.7657595 , 2.0369127 ,-2.5619278 ,-3.4452975 ,-4.5852203 ,-1.137643
diff --git a/compiler/pota-quantization-value-test/test_inputs/TransposeConv_001/layer/uint8/0.txt b/compiler/pota-quantization-value-test/test_inputs/TransposeConv_001/layer/uint8/0.txt
new file mode 100644
index 000000000..e9db48f9e
--- /dev/null
+++ b/compiler/pota-quantization-value-test/test_inputs/TransposeConv_001/layer/uint8/0.txt
@@ -0,0 +1 @@
+-1.4124781 , 0.42694193, 1.1734594 ,-3.5111153 ,-2.9756174 , 1.3682148 ,-2.318465 , 2.198896 ,-4.5043235 , 3.1775594 ,-0.42802384,-1.4872279 , 1.3821319 ,-4.771963 ,-0.12837897, 4.132799 , 3.697655 , 2.0807178 ,-3.621293 , 2.121878 ,-0.25654107, 0.42100102,-1.4009671 ,-2.9733627 ,-0.7058871 ,-2.831215 , 3.5669627 , 2.1420689 ,-1.8789555 , 0.8104939 ,-2.0503597 , 1.7788508
diff --git a/compiler/pota-quantization-value-test/test_inputs/TransposeConv_001/layer/uint8/1.txt b/compiler/pota-quantization-value-test/test_inputs/TransposeConv_001/layer/uint8/1.txt
new file mode 100644
index 000000000..479d062f1
--- /dev/null
+++ b/compiler/pota-quantization-value-test/test_inputs/TransposeConv_001/layer/uint8/1.txt
@@ -0,0 +1 @@
+ 3.4726453 , 3.0497985 ,-4.234619 ,-1.0526706 , 1.7278554 ,-3.341614 , 4.54768 , 3.0954597 ,-3.735109 , 2.8810751 ,-2.5381427 ,-3.2360535 ,-1.5378917 , 2.3052745 ,-3.170938 ,-3.327242 , 2.0654576 ,-2.2294598 ,-1.881382 , 0.13216451,-4.2825613 , 0.26616526, 4.6196365 ,-0.88623226, 1.7103885 ,-1.5865034 ,-3.9114466 ,-3.2227128 , 4.909618 , 2.3318915 , 0.84300846, 0.760918
diff --git a/compiler/pota-quantization-value-test/test_inputs/TransposeConv_001/layer/uint8/2.txt b/compiler/pota-quantization-value-test/test_inputs/TransposeConv_001/layer/uint8/2.txt
new file mode 100644
index 000000000..ae28234bd
--- /dev/null
+++ b/compiler/pota-quantization-value-test/test_inputs/TransposeConv_001/layer/uint8/2.txt
@@ -0,0 +1 @@
+-4.6097918,-4.21991 ,-3.9955974, 3.6492047, 2.9191775, 2.8082933, 1.6189331, 0.2730309,-1.5029653,-1.9471445, 4.8758197, 3.3177438, 3.1338058,-2.1281245,-1.7526287,-2.5518703,-1.7746793, 4.0455256,-0.5839861,-4.408046 ,-4.0034447, 1.5858272,-4.5896654, 4.7211285,-4.677515 ,-2.6027086,-4.7896166,-3.5512326,-1.9068764,-2.9705904,-4.854087 ,-4.892111
diff --git a/compiler/pota-quantization-value-test/test_inputs/TransposeConv_001/layer/uint8/3.txt b/compiler/pota-quantization-value-test/test_inputs/TransposeConv_001/layer/uint8/3.txt
new file mode 100644
index 000000000..fd40f84f4
--- /dev/null
+++ b/compiler/pota-quantization-value-test/test_inputs/TransposeConv_001/layer/uint8/3.txt
@@ -0,0 +1 @@
+ 2.1514777e-02, 2.6526773e+00,-3.0477784e+00, 1.3287724e+00,-4.1414630e-01,-1.7295350e-01, 7.6649576e-01,-1.8028022e+00,-7.0781744e-01,-2.5262204e-01,-3.0970418e+00,-1.3165286e+00,-4.6649928e+00, 2.0809033e+00,-1.5739973e+00,-4.0531826e-01,-2.1718202e+00, 2.0146034e+00, 2.5044403e+00,-1.1256610e+00, 1.3536702e+00, 1.0283234e-03,-1.8823910e+00, 4.7122188e+00, 9.4781297e-01, 3.2012525e+00,-5.5164534e-01,-2.6158772e+00,-1.8771547e+00,-3.1689723e+00, 4.9054880e+00,-3.4560370e+00
diff --git a/compiler/pota-quantization-value-test/test_inputs/TransposeConv_001/layer/uint8/4.txt b/compiler/pota-quantization-value-test/test_inputs/TransposeConv_001/layer/uint8/4.txt
new file mode 100644
index 000000000..e81c3b8e5
--- /dev/null
+++ b/compiler/pota-quantization-value-test/test_inputs/TransposeConv_001/layer/uint8/4.txt
@@ -0,0 +1 @@
+-2.0927553 ,-2.107511 ,-1.6963564 , 1.7006218 , 1.4575784 , 0.06095728, 1.2659966 , 4.1905265 , 1.3035946 , 4.9793477 ,-4.3388166 ,-0.23496658, 1.9831208 , 2.6154642 ,-0.2790228 ,-3.1774354 ,-3.178935 ,-1.1564373 ,-0.8199472 ,-2.245698 ,-4.8605046 ,-3.569018 ,-1.4226891 ,-4.1067843 , 2.6078918 ,-3.5830674 , 1.9065963 , 2.435578 ,-3.3216476 , 4.5930347 , 2.9191844 , 1.7885648
diff --git a/compiler/pota-quantization-value-test/test_record_minmax.sh b/compiler/pota-quantization-value-test/test_record_minmax.sh
index eaa462d0c..acb7574c0 100755
--- a/compiler/pota-quantization-value-test/test_record_minmax.sh
+++ b/compiler/pota-quantization-value-test/test_record_minmax.sh
@@ -59,9 +59,9 @@ while [ "$1" != "" ]; do
# Run record-minmax
"${RECORD_MINMAX_PATH}" \
- "${TEST_RESULT_FILE}.fake_quantized.circle" \
- "${TEST_RESULT_FILE}.input.h5" \
- "${TEST_RESULT_FILE}.minmax_recorded.circle"
+ --input_model "${TEST_RESULT_FILE}.fake_quantized.circle" \
+ --input_data "${TESTCASE_FILE}.input.h5" \
+ --output_model "${TEST_RESULT_FILE}.minmax_recorded.circle"
# Dump min/max values (circle-tensordump)
"${CIRCLE_TENSORDUMP_PATH}" \
diff --git a/compiler/record-minmax/CMakeLists.txt b/compiler/record-minmax/CMakeLists.txt
index 862660e06..f8a165bd3 100644
--- a/compiler/record-minmax/CMakeLists.txt
+++ b/compiler/record-minmax/CMakeLists.txt
@@ -19,9 +19,14 @@ target_link_libraries(record-minmax safemain)
target_link_libraries(record-minmax luci_import)
target_link_libraries(record-minmax luci_export)
target_link_libraries(record-minmax luci_interpreter)
+target_link_libraries(record-minmax vconone)
install(TARGETS record-minmax DESTINATION bin)
+if(NOT ENABLE_TEST)
+ return()
+endif(NOT ENABLE_TEST)
+
nnas_find_package(GTest REQUIRED)
GTest_AddTest(record_minmax_function_test "${CMAKE_CURRENT_SOURCE_DIR}/tests/RecordFunction.test.cpp")
target_include_directories(record_minmax_function_test PRIVATE include)
diff --git a/compiler/record-minmax/driver/Driver.cpp b/compiler/record-minmax/driver/Driver.cpp
index ae4fcb7c7..8b09498c3 100644
--- a/compiler/record-minmax/driver/Driver.cpp
+++ b/compiler/record-minmax/driver/Driver.cpp
@@ -17,6 +17,13 @@
#include "RecordMinMax.h"
#include <arser/arser.h>
+#include <vconone/vconone.h>
+
+void print_version(void)
+{
+ std::cout << "record-minmax version " << vconone::get_string() << std::endl;
+ std::cout << vconone::get_copyright() << std::endl;
+}
int entry(const int argc, char **argv)
{
@@ -25,6 +32,13 @@ int entry(const int argc, char **argv)
arser::Arser arser(
"Embedding min/max values of activations to the circle model for post-training quantization");
+ arser.add_argument("--version")
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("Show version information and exit")
+ .exit_with(print_version);
+
arser.add_argument("--input_model")
.nargs(1)
.type(arser::DataType::STR)
@@ -66,7 +80,7 @@ int entry(const int argc, char **argv)
{
std::cout << err.what() << std::endl;
std::cout << arser;
- return 0;
+ return 255;
}
auto input_model_path = arser.get<std::string>("--input_model");
diff --git a/compiler/record-minmax/requires.cmake b/compiler/record-minmax/requires.cmake
index 054503539..f6804cef1 100644
--- a/compiler/record-minmax/requires.cmake
+++ b/compiler/record-minmax/requires.cmake
@@ -1,3 +1,4 @@
require("luci")
require("safemain")
require("arser")
+require("vconone")
diff --git a/compiler/record-minmax/src/HDF5Importer.cpp b/compiler/record-minmax/src/HDF5Importer.cpp
index cf30cd863..a0e65eeb7 100644
--- a/compiler/record-minmax/src/HDF5Importer.cpp
+++ b/compiler/record-minmax/src/HDF5Importer.cpp
@@ -20,6 +20,7 @@
#include <string>
#include <cassert>
+#include <stdexcept>
using Shape = luci_interpreter::Shape;
using DataType = luci_interpreter::DataType;
diff --git a/compiler/record-minmax/src/MinMaxObserver.cpp b/compiler/record-minmax/src/MinMaxObserver.cpp
index 45f0197c8..c22cb4132 100644
--- a/compiler/record-minmax/src/MinMaxObserver.cpp
+++ b/compiler/record-minmax/src/MinMaxObserver.cpp
@@ -38,7 +38,7 @@ void MinMaxObserver::postTensorWrite(const luci::CircleNode *node,
assert(node->opcode() != luci::CircleOpcode::UNPACK);
assert(node->opcode() != luci::CircleOpcode::WHILE);
- if (node->opcode() == luci::CircleOpcode::CONST)
+ if (node->opcode() == luci::CircleOpcode::CIRCLECONST)
{
// node is not activation. Do nothing.
return;
diff --git a/compiler/record-minmax/src/RecordMinMax.cpp b/compiler/record-minmax/src/RecordMinMax.cpp
index d12a0d3ae..17c6aa6ff 100644
--- a/compiler/record-minmax/src/RecordMinMax.cpp
+++ b/compiler/record-minmax/src/RecordMinMax.cpp
@@ -158,7 +158,7 @@ void RecordMinMax::profileData(const std::string &mode, const std::string &input
auto node = iter->first;
auto minmax = iter->second;
- float min, max;
+ float min{0.0f}, max{0.0f};
if (mode == "percentile")
{
min = getNthPercentile(minmax.min_vector, min_percentile);
diff --git a/compiler/record-minmax/tests/RecordFunction.test.cpp b/compiler/record-minmax/tests/RecordFunction.test.cpp
index 13b464db9..e2f135a4e 100644
--- a/compiler/record-minmax/tests/RecordFunction.test.cpp
+++ b/compiler/record-minmax/tests/RecordFunction.test.cpp
@@ -32,6 +32,8 @@ TEST(GetNthPercentileTest, Edge)
EXPECT_FLOAT_NEAR(0, getNthPercentile(input, 0));
EXPECT_FLOAT_NEAR(9, getNthPercentile(input, 100));
+
+ SUCCEED();
}
TEST(GetNthPercentileTest, Simple)
@@ -47,6 +49,8 @@ TEST(GetNthPercentileTest, Simple)
{
EXPECT_FLOAT_NEAR(0.09 * std::floor(i) + 0.045, getNthPercentile(input, i));
}
+
+ SUCCEED();
}
TEST(GetNthPercentileTest, Float)
@@ -61,6 +65,8 @@ TEST(GetNthPercentileTest, Float)
EXPECT_FLOAT_NEAR(2.799942346802177, getNthPercentile(input, 1));
EXPECT_FLOAT_NEAR(7.768503955476342, getNthPercentile(input, 3.14));
EXPECT_FLOAT_NEAR(99.40456084968194, getNthPercentile(input, 99));
+
+ SUCCEED();
}
TEST(GetNthPercentileTest, FloatWithNegative)
@@ -75,6 +81,8 @@ TEST(GetNthPercentileTest, FloatWithNegative)
EXPECT_FLOAT_NEAR(-47.20005765319782, getNthPercentile(input, 1));
EXPECT_FLOAT_NEAR(-42.23149604452366, getNthPercentile(input, 3.14));
EXPECT_FLOAT_NEAR(49.40456084968194, getNthPercentile(input, 99));
+
+ SUCCEED();
}
TEST(GetNthPercentileTest, SigleElement)
@@ -84,6 +92,8 @@ TEST(GetNthPercentileTest, SigleElement)
EXPECT_FLOAT_NEAR(33, getNthPercentile(input, 0));
EXPECT_FLOAT_NEAR(33, getNthPercentile(input, 50));
EXPECT_FLOAT_NEAR(33, getNthPercentile(input, 100));
+
+ SUCCEED();
}
TEST(GetNthPercentileTest, OutOfBoundary_NEG)
@@ -92,6 +102,8 @@ TEST(GetNthPercentileTest, OutOfBoundary_NEG)
EXPECT_THROW(getNthPercentile(input, -1), std::runtime_error);
EXPECT_THROW(getNthPercentile(input, 101), std::runtime_error);
+
+ SUCCEED();
}
TEST(GetNthPercentileTest, EmptyVector_NEG)
@@ -99,6 +111,8 @@ TEST(GetNthPercentileTest, EmptyVector_NEG)
std::vector<float> input;
EXPECT_THROW(getNthPercentile(input, 10), std::runtime_error);
+
+ SUCCEED();
}
} // namespace record_minmax
diff --git a/compiler/tf2circle-value-pbtxt-remote-test/CMakeLists.txt b/compiler/tf2circle-value-pbtxt-remote-test/CMakeLists.txt
index 64dcc28fd..852018e64 100644
--- a/compiler/tf2circle-value-pbtxt-remote-test/CMakeLists.txt
+++ b/compiler/tf2circle-value-pbtxt-remote-test/CMakeLists.txt
@@ -141,7 +141,6 @@ add_custom_command(
COMMAND ${CMAKE_COMMAND} -E echo 'HDF5_EXPORT_ACTION_PATH=\"$<TARGET_FILE:nnkit_HDF5_export_action>\"' >> ${TEST_CONFIG}
COMMAND ${CMAKE_COMMAND} -E echo 'HDF5_IMPORT_ACTION_PATH=\"$<TARGET_FILE:nnkit_HDF5_import_action>\"' >> ${TEST_CONFIG}
COMMAND ${CMAKE_COMMAND} -E echo 'MODEL2NNPKG_PATH=\"${NNAS_PROJECT_SOURCE_DIR}/tools/nnpackage_tool/model2nnpkg/model2nnpkg.sh\"' >> ${TEST_CONFIG}
- COMMAND ${CMAKE_COMMAND} -E echo 'NNPKG_TEST_PATH=\"${NNAS_PROJECT_SOURCE_DIR}/tests/scripts/nnpkg_test.sh\"' >> ${TEST_CONFIG}
COMMAND ${CMAKE_COMMAND} -E echo 'RUNTIME_LIBRARY_PATH=\"${NNAS_PROJECT_SOURCE_DIR}/Product/out/\"' >> ${TEST_CONFIG}
DEPENDS
nnkit-run
diff --git a/compiler/tf2circle-value-pbtxt-remote-test/README.md b/compiler/tf2circle-value-pbtxt-remote-test/README.md
index 5546cc879..0d41b0a48 100644
--- a/compiler/tf2circle-value-pbtxt-remote-test/README.md
+++ b/compiler/tf2circle-value-pbtxt-remote-test/README.md
@@ -36,13 +36,13 @@
#--------------- Remote Machine Setting ---------------#
set(REMOTE_IP "xxx.xxx.xxx.xxx")
set(REMOTE_USER "remote_username")
-
+
#--------------------- Tests list ---------------------#
add(UNIT_Add_000)
add(UNIT_Add_001)
...
```
- - If any Tensorflow model is added, or if `REMOTE_IP` and `REMOTE_USER` is not given, `tf2circle-value-pbtxt-remote-test` will not be created.
+ - If any Tensorflow model is added, or if `REMOTE_IP` and `REMOTE_USER` is not given, `tf2circle-value-pbtxt-remote-test` will not be created.
1. (Optional) ssh authentication
- This test uses `ssh` and `scp` commands, and those commands require a password of remote machine whenever they are called. This means that you should enter the password everytime when `ssh` and `scp` require.
- This test resolves the problem by using `ssh-copy-id`, which copies the public key of host machine to `authorized_keys` of remote machine. Because of that, this test will ask the password of remote machine only once, at the first time. This is the only user interaction while running this test.
@@ -71,7 +71,7 @@
├ Result_latest -> Result_YYMMDD_hhmmss.csv
├ Result_YYMMDD_hhmmss.csv
├ ...
- |
+ |
├ UNIT_Add_000
| ├ metadata
| | ├ MANIFEST
@@ -91,16 +91,16 @@
|
├ ...
```
-- `nnpkg_test.sh`, runtime products and each nnpackage are sent to `REMOTE_WORKDIR` in remote machine.
+- Runtime products and each nnpackage are sent to `REMOTE_WORKDIR` in remote machine.
- (TBD) Modify script not to remove obtained h5 file.
```
REMOTE_WORKDIR
- ├ nnpkg_test.sh
|
├ Product
| â”” out
| ├ bin
| ├ lib
+ | ├ test
| ├ ...
|
├ UNIT_Add_000
diff --git a/compiler/tf2circle-value-pbtxt-remote-test/testall.sh b/compiler/tf2circle-value-pbtxt-remote-test/testall.sh
index ca6fb49c8..c80b00a14 100755
--- a/compiler/tf2circle-value-pbtxt-remote-test/testall.sh
+++ b/compiler/tf2circle-value-pbtxt-remote-test/testall.sh
@@ -30,7 +30,6 @@ echo "-- Found nnkit-run: ${NNKIT_RUN_PATH}"
echo "-- Found TF backend: ${TF_BACKEND_PATH}"
echo "-- Found TF2CIRCLE: ${TF2CIRCLE_PATH}"
echo "-- Found MODEL2NNPKG: ${MODEL2NNPKG_PATH}"
-echo "-- Found nnpkg_test: ${NNPKG_TEST_PATH}"
echo "-- Found Runtime library: ${RUNTIME_LIBRARY_PATH}"
echo "-- Found randomize action: ${RANDOMIZE_ACTION_PATH}"
echo "-- Found HDF5 export action: ${HDF5_EXPORT_ACTION_PATH}"
@@ -42,11 +41,6 @@ if [ -z ${MODEL2NNPKG_PATH} ] || [ ! -f ${MODEL2NNPKG_PATH} ]; then
exit 3
fi
-if [ -z ${NNPKG_TEST_PATH} ] || [ ! -f ${NNPKG_TEST_PATH} ]; then
- echo "nnpkg_test is not found"
- exit 4
-fi
-
# Register remote machine ssh information
cat /dev/zero | ssh-keygen -q -N ""
ssh-copy-id -o ConnectTimeout=5 "${REMOTE_USER}@${REMOTE_IP}"
@@ -61,9 +55,6 @@ fi
ssh "${REMOTE_USER}@${REMOTE_IP}" "mkdir -p ${REMOTE_WORKDIR}/Product/"
scp -r "${RUNTIME_LIBRARY_PATH}" "${REMOTE_USER}@${REMOTE_IP}:${REMOTE_WORKDIR}/Product/"
-# Send nnpkg_test.sh
-scp "${NNPKG_TEST_PATH}" "${REMOTE_USER}@${REMOTE_IP}:${REMOTE_WORKDIR}/"
-
TESTED=()
PASSED=()
FAILED=()
@@ -120,8 +111,8 @@ while [[ $# -ne 0 ]]; do
# Run test_arm_nnpkg in remote machine
scp -r "${WORKDIR}/${PREFIX}/" "${REMOTE_USER}@${REMOTE_IP}:${REMOTE_WORKDIR}/${PREFIX}/"
- ssh "${REMOTE_USER}@${REMOTE_IP}" "cd ${REMOTE_WORKDIR}; ./nnpkg_test.sh -i . -o ${PREFIX}/metadata/tc ${PREFIX}"
-
+ ssh "${REMOTE_USER}@${REMOTE_IP}" "cd ${REMOTE_WORKDIR}; ./Product/out/test/onert-test nnpkg-test -i . -o ${PREFIX}/metadata/tc ${PREFIX}"
+
if [[ $? -eq 0 ]]; then
touch "${PASSED_TAG}"
fi
diff --git a/compiler/tf2nnpackage-value-remote-test/CMakeLists.txt b/compiler/tf2nnpackage-value-remote-test/CMakeLists.txt
index 4a59e8849..255806ce8 100644
--- a/compiler/tf2nnpackage-value-remote-test/CMakeLists.txt
+++ b/compiler/tf2nnpackage-value-remote-test/CMakeLists.txt
@@ -33,12 +33,12 @@ endforeach()
get_target_property(ARTIFACTS_SRC_PATH testDataGenerator SOURCE_DIR)
-# In this test, only the runtime test is performed because the test from tf to
-# nnpackage is done in common-artifacts, and for this runtime test, generation of
+# In this test, only the runtime test is performed because the test from tf to
+# nnpackage is done in common-artifacts, and for this runtime test, generation of
# test data is required. And, tcgenerate in ${ARTIFACTS_SRC_PATH}/exclude.lst
# means it won't generate test data, which is why below "tcgenerate" macro excludes
-# specific opearators from runtime test.
-# Also, since circlize and optimize macro included in `exclude.lst` file is only
+# specific opearators from runtime test.
+# Also, since circlize and optimize macro included in `exclude.lst` file is only
# needed in common-artifacts, it has no function here.
macro(circlize)
endmacro()
@@ -72,7 +72,6 @@ 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 'NNPKG_TEST_PATH=\"${NNAS_PROJECT_SOURCE_DIR}/tests/scripts/nnpkg_test.sh\"' >> ${TEST_CONFIG}
COMMAND ${CMAKE_COMMAND} -E echo 'RUNTIME_LIBRARY_PATH=\"${NNAS_PROJECT_SOURCE_DIR}/Product/out/\"' >> ${TEST_CONFIG}
COMMENT "Generate test configuration"
)
diff --git a/compiler/tf2nnpackage-value-remote-test/README.md b/compiler/tf2nnpackage-value-remote-test/README.md
index 36436fc6b..65f307b13 100644
--- a/compiler/tf2nnpackage-value-remote-test/README.md
+++ b/compiler/tf2nnpackage-value-remote-test/README.md
@@ -15,7 +15,7 @@
set(REMOTE_IP "xxx.xxx.xxx.xxx")
set(REMOTE_USER "remote_username")
```
- - If any recipe is added, or if `REMOTE_IP` and `REMOTE_USER` is not given, `tf2nnpackage-value-remote-test` will not be created.
+ - If any recipe is added, or if `REMOTE_IP` and `REMOTE_USER` is not given, `tf2nnpackage-value-remote-test` will not be created.
1. (Optional) ssh authentication
- This test uses `ssh` and `scp` commands, and those commands require a password of remote machine whenever they are called. This means that you should enter the password everytime when `ssh` and `scp` require.
- This test resolves the problem by using `ssh-copy-id`, which copies the public key of host machine to `authorized_keys` of remote machine. Because of that, this test will ask the password of remote machine only once, at the first time. This is the only user interaction while running this test.
@@ -39,7 +39,7 @@
### Generated Files While Running
- All related files(`pb`, `circle`, `h5` ... etc.) are taken from `build/compiler/common-artifacts` folder.
-- `nnpkg_test.sh`, runtime products and each nnpackage are sent to `REMOTE_WORKDIR` in remote machine.
+- Runtime products and each nnpackage are sent to `REMOTE_WORKDIR` in remote machine.
- Each test result is generated in `build/compiler/common-artifacts` with the name `${RECIPE}.log`
### Check Test Result
diff --git a/compiler/tf2nnpackage-value-remote-test/testall.sh b/compiler/tf2nnpackage-value-remote-test/testall.sh
index f1c9789b3..ca672a3eb 100755
--- a/compiler/tf2nnpackage-value-remote-test/testall.sh
+++ b/compiler/tf2nnpackage-value-remote-test/testall.sh
@@ -27,15 +27,9 @@ RESULT_CSV="${BINDIR}/Result_${CURRENT_DATETIME}.csv"
source "${CONFIG_PATH}"
-echo "-- Found nnpkg_test: ${NNPKG_TEST_PATH}"
echo "-- Found Runtime library: ${RUNTIME_LIBRARY_PATH}"
echo "-- Found workdir: ${WORKDIR}"
-if [ -z ${NNPKG_TEST_PATH} ] || [ ! -f ${NNPKG_TEST_PATH} ]; then
- echo "nnpkg_test is not found"
- exit 4
-fi
-
# Register remote machine ssh information
cat /dev/zero | ssh-keygen -q -N ""
ssh-copy-id -o ConnectTimeout=5 "${REMOTE_USER}@${REMOTE_IP}"
@@ -50,9 +44,6 @@ fi
ssh "${REMOTE_USER}@${REMOTE_IP}" "mkdir -p ${REMOTE_WORKDIR}/Product/"
scp -r "${RUNTIME_LIBRARY_PATH}" "${REMOTE_USER}@${REMOTE_IP}:${REMOTE_WORKDIR}/Product/"
-# Send nnpkg_test.sh
-scp "${NNPKG_TEST_PATH}" "${REMOTE_USER}@${REMOTE_IP}:${REMOTE_WORKDIR}/"
-
TESTED=()
PASSED=()
FAILED=()
@@ -84,8 +75,8 @@ while [[ $# -ne 0 ]]; do
PREFIX=${PREFIX}.opt ;
fi
scp -r "${PREFIX}/" "${REMOTE_USER}@${REMOTE_IP}:${REMOTE_WORKDIR}/${PREFIX}/"
- ssh "${REMOTE_USER}@${REMOTE_IP}" "cd ${REMOTE_WORKDIR}; ./nnpkg_test.sh ${PREFIX}"
-
+ ssh "${REMOTE_USER}@${REMOTE_IP}" "cd ${REMOTE_WORKDIR}; ./Product/out/test/onert-test nnpkg-test ${PREFIX}"
+
if [[ $? -eq 0 ]]; then
touch "${BINDIR}/${PASSED_TAG}"
fi
diff --git a/compiler/tf2tfliteV2/README.md b/compiler/tf2tfliteV2/README.md
index 13359aab1..0a90735cb 100644
--- a/compiler/tf2tfliteV2/README.md
+++ b/compiler/tf2tfliteV2/README.md
@@ -47,6 +47,9 @@ python tf2tfliteV2.py \
-h, --help show this help message and exit
--v1 Use TensorFlow Lite Converter 1.x
--v2 Use TensorFlow Lite Converter 2.x
+ --graph_def Use graph def file(default)
+ --saved_model Use saved model
+ --keras_model Use keras model
-i INPUT_PATH, --input_path INPUT_PATH
Full filepath of the input file.
-o OUTPUT_PATH, --output_path OUTPUT_PATH
@@ -55,7 +58,8 @@ python tf2tfliteV2.py \
Names of the input arrays, comma-separated.
-s INPUT_SHAPES, --input_shapes INPUT_SHAPES
Shapes corresponding to --input_arrays, colon-
- separated.
+ separated.(ex:"1,4,4,3:1,20,20,3")
-O OUTPUT_ARRAYS, --output_arrays OUTPUT_ARRAYS
Names of the output arrays, comma-separated.
+
```
diff --git a/compiler/tf2tfliteV2/tf2tfliteV2.py b/compiler/tf2tfliteV2/tf2tfliteV2.py
index 82d6ee232..c51dabde0 100755
--- a/compiler/tf2tfliteV2/tf2tfliteV2.py
+++ b/compiler/tf2tfliteV2/tf2tfliteV2.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
# Copyright (C) 2018 The TensorFlow Authors
@@ -48,6 +48,27 @@ def _get_parser():
converter_version.add_argument(
"--v2", action="store_true", help="Use TensorFlow Lite Converter 2.x")
+ # Input model format
+ model_format_arg = parser.add_mutually_exclusive_group()
+ model_format_arg.add_argument(
+ "--graph_def",
+ action="store_const",
+ dest="model_format",
+ const="graph_def",
+ help="Use graph def file(default)")
+ model_format_arg.add_argument(
+ "--saved_model",
+ action="store_const",
+ dest="model_format",
+ const="saved_model",
+ help="Use saved model")
+ model_format_arg.add_argument(
+ "--keras_model",
+ action="store_const",
+ dest="model_format",
+ const="keras_model",
+ help="Use keras model")
+
# Input and output path.
parser.add_argument(
"-i",
@@ -83,6 +104,8 @@ def _get_parser():
help="Names of the output arrays, comma-separated.",
required=True)
+ # Set default value
+ parser.set_defaults(model_format="graph_def")
return parser
@@ -122,17 +145,26 @@ def _parse_array(arrays, type_fn=str):
def _v1_convert(flags):
- input_shapes = None
- if flags.input_shapes:
- input_arrays = _parse_array(flags.input_arrays)
- input_shapes_list = [
- _parse_array(shape, type_fn=int) for shape in flags.input_shapes.split(":")
- ]
- input_shapes = dict(list(zip(input_arrays, input_shapes_list)))
-
- converter = tf.compat.v1.lite.TFLiteConverter.from_frozen_graph(
- flags.input_path, _parse_array(flags.input_arrays),
- _parse_array(flags.output_arrays), input_shapes)
+ if flags.model_format == "graph_def":
+ input_shapes = None
+ if flags.input_shapes:
+ input_arrays = _parse_array(flags.input_arrays)
+ input_shapes_list = [
+ _parse_array(shape, type_fn=int)
+ for shape in flags.input_shapes.split(":")
+ ]
+ input_shapes = dict(list(zip(input_arrays, input_shapes_list)))
+
+ converter = tf.compat.v1.lite.TFLiteConverter.from_frozen_graph(
+ flags.input_path, _parse_array(flags.input_arrays),
+ _parse_array(flags.output_arrays), input_shapes)
+
+ if flags.model_format == "saved_model":
+ converter = tf.compat.v1.lite.TFLiteConverter.from_saved_model(flags.input_path)
+
+ if flags.model_format == "keras_model":
+ converter = tf.compat.v1.lite.TFLiteConverter.from_keras_model_file(
+ flags.input_path)
converter.allow_custom_ops = True
@@ -141,27 +173,35 @@ def _v1_convert(flags):
def _v2_convert(flags):
- file_content = open(flags.input_path, 'rb').read()
- try:
- graph_def = tf.compat.v1.GraphDef()
- graph_def.ParseFromString(file_content)
- except (_text_format.ParseError, DecodeError):
+ if flags.model_format == "graph_def":
+ file_content = open(flags.input_path, 'rb').read()
try:
- _text_format.Merge(file_content, graph_def)
+ graph_def = tf.compat.v1.GraphDef()
+ graph_def.ParseFromString(file_content)
except (_text_format.ParseError, DecodeError):
- raise IOError("Unable to parse input file '{}'.".format(flags.input_path))
-
- wrap_func = wrap_frozen_graph(
- graph_def,
- inputs=[
- _str + ":0" if len(_str.split(":")) == 1 else _str
- for _str in _parse_array(flags.input_arrays)
- ],
- outputs=[
- _str + ":0" if len(_str.split(":")) == 1 else _str
- for _str in _parse_array(flags.output_arrays)
- ])
- converter = tf.lite.TFLiteConverter.from_concrete_functions([wrap_func])
+ try:
+ _text_format.Merge(file_content, graph_def)
+ except (_text_format.ParseError, DecodeError):
+ raise IOError("Unable to parse input file '{}'.".format(flags.input_path))
+
+ wrap_func = wrap_frozen_graph(
+ graph_def,
+ inputs=[
+ _str + ":0" if len(_str.split(":")) == 1 else _str
+ for _str in _parse_array(flags.input_arrays)
+ ],
+ outputs=[
+ _str + ":0" if len(_str.split(":")) == 1 else _str
+ for _str in _parse_array(flags.output_arrays)
+ ])
+ converter = tf.lite.TFLiteConverter.from_concrete_functions([wrap_func])
+
+ if flags.model_format == "saved_model":
+ converter = tf.lite.TFLiteConverter.from_saved_model(flags.input_path)
+
+ if flags.model_format == "keras_model":
+ keras_model = tf.keras.models.load_model(flags.input_path)
+ converter = tf.lite.TFLiteConverter.from_keras_model(keras_model)
converter.allow_custom_ops = True
converter.experimental_new_converter = True
diff --git a/compiler/tfl-verify/CMakeLists.txt b/compiler/tfl-verify/CMakeLists.txt
index d33059fde..4421a4660 100644
--- a/compiler/tfl-verify/CMakeLists.txt
+++ b/compiler/tfl-verify/CMakeLists.txt
@@ -6,6 +6,7 @@ file(GLOB_RECURSE SOURCES "src/*.cpp")
add_executable(tfl-verify ${SOURCES})
target_include_directories(tfl-verify PRIVATE src)
+target_link_libraries(tfl-verify arser)
target_link_libraries(tfl-verify foder)
target_link_libraries(tfl-verify mio_tflite)
target_link_libraries(tfl-verify safemain)
diff --git a/compiler/tfl-verify/requires.cmake b/compiler/tfl-verify/requires.cmake
index ed6b84db5..79503f325 100644
--- a/compiler/tfl-verify/requires.cmake
+++ b/compiler/tfl-verify/requires.cmake
@@ -1,3 +1,4 @@
+require("arser")
require("foder")
require("mio-tflite")
require("safemain")
diff --git a/compiler/tfl-verify/src/Driver.cpp b/compiler/tfl-verify/src/Driver.cpp
index 81f6d5489..6d1897607 100644
--- a/compiler/tfl-verify/src/Driver.cpp
+++ b/compiler/tfl-verify/src/Driver.cpp
@@ -16,22 +16,31 @@
#include "VerifyFlatBuffers.h"
+#include <arser/arser.h>
+
#include <iostream>
#include <memory>
#include <string>
int entry(int argc, char **argv)
{
- if (argc != 2)
+ arser::Arser arser;
+ arser.add_argument("tflite").type(arser::DataType::STR).help("TFLite file path to verify");
+
+ try
{
- std::cerr << "ERROR: Failed to parse arguments" << std::endl;
- std::cerr << std::endl;
- std::cerr << "USAGE: " << argv[0] << " [tflite]" << std::endl;
+ arser.parse(argc, argv);
+ }
+ catch (const std::runtime_error &err)
+ {
+ std::cout << err.what() << std::endl;
+ std::cout << arser;
return 255;
}
+
auto verifier = std::make_unique<VerifyFlatbuffers>();
- std::string model_file = argv[argc - 1];
+ std::string model_file = arser.get<std::string>("tflite");
std::cout << "[ RUN ] Check " << model_file << std::endl;
diff --git a/compiler/tflchef/core/src/ModelChef.cpp b/compiler/tflchef/core/src/ModelChef.cpp
index 932a649c5..692ce48c1 100644
--- a/compiler/tflchef/core/src/ModelChef.cpp
+++ b/compiler/tflchef/core/src/ModelChef.cpp
@@ -413,6 +413,7 @@ template <typename T> void cook_graph(const T &graph, CookParams &cp)
quant_builder.add_min(quant_min);
quant_builder.add_scale(quant_scale);
quant_builder.add_zero_point(quant_zero_point);
+ quant_builder.add_quantized_dimension(quant.quantized_dimension());
// Update QuantizationParameters Index
quant_index = quant_builder.Finish();
diff --git a/compiler/tflchef/core/src/Op/NonMaxSuppressionV4.cpp b/compiler/tflchef/core/src/Op/NonMaxSuppressionV4.cpp
new file mode 100644
index 000000000..eadd62cc6
--- /dev/null
+++ b/compiler/tflchef/core/src/Op/NonMaxSuppressionV4.cpp
@@ -0,0 +1,30 @@
+/*
+ * 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 "NonMaxSuppressionV4.h"
+
+flatbuffers::Offset<void> NonMaxSuppressionV4Chef::value(flatbuffers::FlatBufferBuilder &fbb) const
+{
+ tflite::NonMaxSuppressionV4OptionsBuilder options_builder{fbb};
+
+ return options_builder.Finish().Union();
+}
+
+std::unique_ptr<OpChef>
+NonMaxSuppressionV4ChefFactory::create(const tflchef::Operation *operation) const
+{
+ return std::unique_ptr<OpChef>{new NonMaxSuppressionV4Chef{operation}};
+}
diff --git a/compiler/tflchef/core/src/Op/NonMaxSuppressionV4.h b/compiler/tflchef/core/src/Op/NonMaxSuppressionV4.h
new file mode 100644
index 000000000..a8e783d53
--- /dev/null
+++ b/compiler/tflchef/core/src/Op/NonMaxSuppressionV4.h
@@ -0,0 +1,52 @@
+/*
+ * 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 __OP_NON_MAX_SUPPRESSION_V4_H__
+#define __OP_NON_MAX_SUPPRESSION_V4_H__
+
+#include "OpChef.h"
+
+class NonMaxSuppressionV4Chef final : public OpChef
+{
+public:
+ explicit NonMaxSuppressionV4Chef(const tflchef::Operation *operation) : _operation{operation}
+ {
+ // DO NOTHING
+ }
+
+public:
+ tflite::BuiltinOperator code(void) const override
+ {
+ return tflite::BuiltinOperator_NON_MAX_SUPPRESSION_V4;
+ }
+
+ tflite::BuiltinOptions type(void) const override
+ {
+ return tflite::BuiltinOptions_NonMaxSuppressionV4Options;
+ }
+
+ flatbuffers::Offset<void> value(flatbuffers::FlatBufferBuilder &fbb) const override;
+
+private:
+ const tflchef::Operation *_operation;
+};
+
+struct NonMaxSuppressionV4ChefFactory final : public OpChefFactory
+{
+ std::unique_ptr<OpChef> create(const tflchef::Operation *operation) const override;
+};
+
+#endif // __OP_NON_MAX_SUPPRESSION_V4_H__
diff --git a/compiler/tflchef/core/src/Op/PadV2.cpp b/compiler/tflchef/core/src/Op/PadV2.cpp
new file mode 100644
index 000000000..bfa2289e5
--- /dev/null
+++ b/compiler/tflchef/core/src/Op/PadV2.cpp
@@ -0,0 +1,28 @@
+/*
+ * 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 "PadV2.h"
+
+flatbuffers::Offset<void> PadV2Chef::value(flatbuffers::FlatBufferBuilder &fbb) const
+{
+ tflite::PadV2OptionsBuilder padv2_options_builder{fbb};
+ return padv2_options_builder.Finish().Union();
+}
+
+std::unique_ptr<OpChef> PadV2ChefFactory::create(const tflchef::Operation *operation) const
+{
+ return std::unique_ptr<OpChef>{new PadV2Chef{operation}};
+}
diff --git a/compiler/tflchef/core/src/Op/PadV2.h b/compiler/tflchef/core/src/Op/PadV2.h
new file mode 100644
index 000000000..d15532390
--- /dev/null
+++ b/compiler/tflchef/core/src/Op/PadV2.h
@@ -0,0 +1,46 @@
+/*
+ * 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 __OP_PADV2_H__
+#define __OP_PADV2_H__
+
+#include "OpChef.h"
+
+class PadV2Chef final : public OpChef
+{
+public:
+ explicit PadV2Chef(const tflchef::Operation *operation) : _operation{operation}
+ {
+ // DO NOTHING
+ }
+
+public:
+ tflite::BuiltinOperator code(void) const override { return tflite::BuiltinOperator_PADV2; }
+
+ tflite::BuiltinOptions type(void) const override { return tflite::BuiltinOptions_PadV2Options; }
+
+ flatbuffers::Offset<void> value(flatbuffers::FlatBufferBuilder &fbb) const override;
+
+private:
+ const tflchef::Operation *_operation;
+};
+
+struct PadV2ChefFactory final : public OpChefFactory
+{
+ std::unique_ptr<OpChef> create(const tflchef::Operation *operation) const override;
+};
+
+#endif // __OP_PADV2_H__
diff --git a/compiler/tflchef/core/src/OpChef.def b/compiler/tflchef/core/src/OpChef.def
index 263725a24..244186265 100644
--- a/compiler/tflchef/core/src/OpChef.def
+++ b/compiler/tflchef/core/src/OpChef.def
@@ -55,10 +55,12 @@ OP_CHEF(Minimum, MinimumChefFactory)
OP_CHEF(MirrorPad, MirrorPadChefFactory)
OP_CHEF(Mul, MulChefFactory)
OP_CHEF(Neg, NegChefFactory)
+OP_CHEF(NonMaxSuppressionV4, NonMaxSuppressionV4ChefFactory)
OP_CHEF(NotEqual, NotEqualChefFactory)
OP_CHEF(OneHot, OneHotChefFactory)
OP_CHEF(Pack, PackChefFactory)
OP_CHEF(Pad, PadChefFactory)
+OP_CHEF(PadV2, PadV2ChefFactory)
OP_CHEF(Pow, PowChefFactory)
OP_CHEF(PRelu, PReluChefFactory)
OP_CHEF(Range, RangeChefFactory)
diff --git a/compiler/tflchef/core/src/OpChefs.h b/compiler/tflchef/core/src/OpChefs.h
index 55c37ebfb..5b2e89bd9 100644
--- a/compiler/tflchef/core/src/OpChefs.h
+++ b/compiler/tflchef/core/src/OpChefs.h
@@ -68,10 +68,12 @@
#include "Op/MirrorPad.h"
#include "Op/Mul.h"
#include "Op/Neg.h"
+#include "Op/NonMaxSuppressionV4.h"
#include "Op/NotEqual.h"
#include "Op/OneHot.h"
#include "Op/Pack.h"
#include "Op/Pad.h"
+#include "Op/PadV2.h"
#include "Op/Pow.h"
#include "Op/PRelu.h"
#include "Op/Range.h"
diff --git a/compiler/tflchef/proto/tflchef.proto b/compiler/tflchef/proto/tflchef.proto
index 792503bc9..70b966ec3 100644
--- a/compiler/tflchef/proto/tflchef.proto
+++ b/compiler/tflchef/proto/tflchef.proto
@@ -35,6 +35,7 @@ message TensorQuantization {
repeated float max = 2;
repeated float scale = 3;
repeated int64 zero_point = 4;
+ optional int32 quantized_dimension = 5 [default = 0];
}
message Operand {
@@ -153,6 +154,10 @@ message PadOptions {
// None
}
+message PadV2Options {
+ // None
+}
+
message MirrorPadOptions {
optional MirrorPadMode mode = 1 [default = REFLECT];
}
@@ -362,6 +367,10 @@ message GatherNdOptions {
// None
}
+message NonMaxSuppressionV4Options {
+ // None
+}
+
message NotEqualOptions {
// None
}
@@ -507,7 +516,7 @@ message Operation {
optional LogSoftmaxOptions log_softmax_options = 168;
// DequantizeOptions 169
optional NegOptions neg_options = 170;
- // PadV2Options 171
+ optional PadV2Options padv2_options = 171;
optional LessEqualOptions lessequal_options = 172;
optional SliceOptions slice_options = 173;
optional TransposeConvOptions transpose_conv_options = 174;
@@ -534,7 +543,7 @@ message Operation {
optional MatrixSetDiagOptions matrix_set_diag_options = 195;
// HardSwishOptions 196
optional DepthToSpaceOptions depth_to_space_options = 197;
- // NonMaxSuppressionV4Options 198
+ optional NonMaxSuppressionV4Options non_max_suppression_v4_options = 198;
// NonMaxSuppressionV5Options 199
optional ScatterNdOptions scatter_nd_options = 200;
optional NotEqualOptions notequal_options = 201;
diff --git a/compiler/tflchef/tflite/src/Op/NonMaxSuppressionV4.cpp b/compiler/tflchef/tflite/src/Op/NonMaxSuppressionV4.cpp
new file mode 100644
index 000000000..ad9921970
--- /dev/null
+++ b/compiler/tflchef/tflite/src/Op/NonMaxSuppressionV4.cpp
@@ -0,0 +1,56 @@
+/*
+ * 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 "NonMaxSuppressionV4.h"
+
+#include "Convert.h"
+#include "FillerHelper.h"
+
+namespace tflchef
+{
+
+void TFliteOpNonMaxSuppressionV4::filler(const tflite::Operator *op, TFliteImport *import,
+ tflchef::ModelRecipe *model_recipe) const
+{
+ const auto &inputs = *op->inputs();
+
+ const tflite::Tensor *max_output_size_tensor = import->tensors()->Get(inputs[2]);
+ assert(max_output_size_tensor->type() == tflite::TensorType::TensorType_INT32);
+
+ const tflite::Tensor *iou_threshold_tensor = import->tensors()->Get(inputs[3]);
+ assert(iou_threshold_tensor->type() == tflite::TensorType::TensorType_FLOAT32);
+
+ const tflite::Tensor *score_threshold_tensor = import->tensors()->Get(inputs[4]);
+ assert(score_threshold_tensor->type() == tflite::TensorType::TensorType_FLOAT32);
+
+ for (int32_t index = 2; index < 5; ++index)
+ {
+ fill_tensor_to_import(index, import);
+ }
+}
+
+tflchef::Operation *TFliteOpNonMaxSuppressionV4::build(const tflite::Operator *op,
+ TFliteImport *import,
+ tflchef::ModelRecipe *model_recipe) const
+{
+ auto operation = model_recipe->add_operation();
+
+ operation->set_type("NonMaxSuppressionV4");
+
+ return operation;
+}
+
+} // namespace tflchef
diff --git a/compiler/tflchef/tflite/src/Op/NonMaxSuppressionV4.h b/compiler/tflchef/tflite/src/Op/NonMaxSuppressionV4.h
new file mode 100644
index 000000000..114a2ad2f
--- /dev/null
+++ b/compiler/tflchef/tflite/src/Op/NonMaxSuppressionV4.h
@@ -0,0 +1,39 @@
+/*
+ * 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 __TFLITE_OP_NON_MAX_SUPPRESSION_V4_H__
+#define __TFLITE_OP_NON_MAX_SUPPRESSION_V4_H__
+
+#include "TFliteOpChef.h"
+
+namespace tflchef
+{
+
+/**
+ * @brief tflchef operator builder for NON_MAX_SUPPRESSION_V4
+ */
+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;
+};
+
+} // namespace tflchef
+
+#endif // __TFLITE_OP_NON_MAX_SUPPRESSION_V4_H__
diff --git a/compiler/tflchef/tflite/src/Op/PadV2.cpp b/compiler/tflchef/tflite/src/Op/PadV2.cpp
new file mode 100644
index 000000000..0b1c9f3b2
--- /dev/null
+++ b/compiler/tflchef/tflite/src/Op/PadV2.cpp
@@ -0,0 +1,42 @@
+/*
+ * 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 "PadV2.h"
+
+#include "FillerHelper.h"
+
+namespace tflchef
+{
+
+void TFliteOpPadV2::filler(const tflite::Operator *op, TFliteImport *import,
+ tflchef::ModelRecipe *model_recipe) const
+{
+ // Filler for paddings and constant_values
+ fill_tensor_to_import(1, import);
+ fill_tensor_to_import(2, import);
+}
+
+tflchef::Operation *TFliteOpPadV2::build(const tflite::Operator *op, TFliteImport *import,
+ tflchef::ModelRecipe *model_recipe) const
+{
+ auto operation = model_recipe->add_operation();
+
+ operation->set_type("PadV2");
+
+ return operation;
+}
+
+} // namespace tflchef
diff --git a/compiler/tflchef/tflite/src/Op/PadV2.h b/compiler/tflchef/tflite/src/Op/PadV2.h
new file mode 100644
index 000000000..3aa474b92
--- /dev/null
+++ b/compiler/tflchef/tflite/src/Op/PadV2.h
@@ -0,0 +1,39 @@
+/*
+ * 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 __TFLITE_OP_PADV2_H__
+#define __TFLITE_OP_PADV2_H__
+
+#include "TFliteOpChef.h"
+
+namespace tflchef
+{
+
+/**
+ * @brief tflchef operator builder for PADV2
+ */
+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;
+};
+
+} // namespace tflchef
+
+#endif // __TFLITE_OP_PADV2_H__
diff --git a/compiler/tflchef/tflite/src/Op/TransposeConv.cpp b/compiler/tflchef/tflite/src/Op/TransposeConv.cpp
index 7e772b954..4e7adf6c6 100644
--- a/compiler/tflchef/tflite/src/Op/TransposeConv.cpp
+++ b/compiler/tflchef/tflite/src/Op/TransposeConv.cpp
@@ -35,6 +35,10 @@ void TFliteOpTransposeConv::filler(const tflite::Operator *op, TFliteImport *imp
auto vec = extract_buffer<int32_t>(buffer);
import->set_tensor_filler(inputs[0], vec);
}
+
+ // filter
+ const tflite::Tensor *filter_tensor = import->tensors()->Get(inputs[1]);
+ import->set_tensor_filler(inputs[1]);
}
tflchef::Operation *TFliteOpTransposeConv::build(const tflite::Operator *op, TFliteImport *import,
diff --git a/compiler/tflchef/tflite/src/RecipeChef.cpp b/compiler/tflchef/tflite/src/RecipeChef.cpp
index db62d0e40..088961c1c 100644
--- a/compiler/tflchef/tflite/src/RecipeChef.cpp
+++ b/compiler/tflchef/tflite/src/RecipeChef.cpp
@@ -184,6 +184,8 @@ std::unique_ptr<ModelRecipe> generate_recipe(const tflite::Model *model)
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());
}
}
diff --git a/compiler/tflchef/tflite/src/TFliteOpChefs.h b/compiler/tflchef/tflite/src/TFliteOpChefs.h
index ad52af1c2..de14e37d1 100644
--- a/compiler/tflchef/tflite/src/TFliteOpChefs.h
+++ b/compiler/tflchef/tflite/src/TFliteOpChefs.h
@@ -68,10 +68,12 @@
#include "Op/MirrorPad.h"
#include "Op/Mul.h"
#include "Op/Neg.h"
+#include "Op/NonMaxSuppressionV4.h"
#include "Op/NotEqual.h"
#include "Op/OneHot.h"
#include "Op/Pack.h"
#include "Op/Pad.h"
+#include "Op/PadV2.h"
#include "Op/Pow.h"
#include "Op/PRelu.h"
#include "Op/Range.h"
diff --git a/compiler/tflchef/tflite/src/TFliteOpRegistry.h b/compiler/tflchef/tflite/src/TFliteOpRegistry.h
index 0a44b3f06..8d33007be 100644
--- a/compiler/tflchef/tflite/src/TFliteOpRegistry.h
+++ b/compiler/tflchef/tflite/src/TFliteOpRegistry.h
@@ -105,10 +105,12 @@ private:
REG_TFL_OP(MIRROR_PAD, TFliteOpMirrorPad);
REG_TFL_OP(MUL, TFliteOpMul);
REG_TFL_OP(NEG, TFliteOpNeg);
+ REG_TFL_OP(NON_MAX_SUPPRESSION_V4, TFliteOpNonMaxSuppressionV4);
REG_TFL_OP(NOT_EQUAL, TFliteOpNotEqual);
REG_TFL_OP(ONE_HOT, TFliteOpOneHot);
REG_TFL_OP(PACK, TFliteOpPack);
REG_TFL_OP(PAD, TFliteOpPad);
+ REG_TFL_OP(PADV2, TFliteOpPadV2);
REG_TFL_OP(POW, TFliteOpPow);
REG_TFL_OP(PRELU, TFliteOpPRelu);
REG_TFL_OP(RANGE, TFliteOpRange);
diff --git a/compiler/tflchef/tools/file/Driver.cpp b/compiler/tflchef/tools/file/Driver.cpp
index cecfeeb3e..46e5b5583 100644
--- a/compiler/tflchef/tools/file/Driver.cpp
+++ b/compiler/tflchef/tools/file/Driver.cpp
@@ -41,7 +41,7 @@ int entry(int argc, char **argv)
{
std::cout << err.what() << std::endl;
std::cout << arser;
- return 0;
+ return 255;
}
int32_t model_version = 1;
diff --git a/compiler/tflchef/tools/reverse/Driver.cpp b/compiler/tflchef/tools/reverse/Driver.cpp
index 1116dec34..4d795a3d0 100644
--- a/compiler/tflchef/tools/reverse/Driver.cpp
+++ b/compiler/tflchef/tools/reverse/Driver.cpp
@@ -38,7 +38,7 @@ int entry(int argc, char **argv)
{
std::cout << err.what() << std::endl;
std::cout << arser;
- return 0;
+ return 255;
}
std::string tflite_path = arser.get<std::string>("tflite");
diff --git a/compiler/tfldump/driver/Driver.cpp b/compiler/tfldump/driver/Driver.cpp
index 3961d2f17..38c9c062f 100644
--- a/compiler/tfldump/driver/Driver.cpp
+++ b/compiler/tfldump/driver/Driver.cpp
@@ -33,7 +33,7 @@ int entry(int argc, char **argv)
{
std::cout << err.what() << '\n';
std::cout << arser;
- return 0;
+ return 255;
}
std::string tflite_path = arser.get<std::string>("tflite");
diff --git a/compiler/tfldump/src/OpPrinter.cpp b/compiler/tfldump/src/OpPrinter.cpp
index 9fc1a6456..df027c3e3 100644
--- a/compiler/tfldump/src/OpPrinter.cpp
+++ b/compiler/tfldump/src/OpPrinter.cpp
@@ -676,6 +676,7 @@ OpPrinterRegistry::OpPrinterRegistry()
_op_map[tflite::BuiltinOperator_MAX_POOL_2D] = make_unique<Pool2DPrinter>();
_op_map[tflite::BuiltinOperator_MIRROR_PAD] = make_unique<MirrorPadPrinter>();
_op_map[tflite::BuiltinOperator_MUL] = make_unique<MulPrinter>();
+ // There is no Option for NON_MAX_SUPPRESSION_V4
_op_map[tflite::BuiltinOperator_ONE_HOT] = make_unique<OneHotPrinter>();
_op_map[tflite::BuiltinOperator_PACK] = make_unique<PackPrinter>();
// There is no Option for PAD
diff --git a/compiler/tflite2circle/CMakeLists.txt b/compiler/tflite2circle/CMakeLists.txt
index a0a2e026b..b1d1f6149 100644
--- a/compiler/tflite2circle/CMakeLists.txt
+++ b/compiler/tflite2circle/CMakeLists.txt
@@ -14,5 +14,6 @@ target_link_libraries(tflite2circle arser)
target_link_libraries(tflite2circle safemain)
target_link_libraries(tflite2circle mio_tflite)
target_link_libraries(tflite2circle mio_circle)
+target_link_libraries(tflite2circle vconone)
install(TARGETS tflite2circle DESTINATION bin)
diff --git a/compiler/tflite2circle/driver/Driver.cpp b/compiler/tflite2circle/driver/Driver.cpp
index 67b8e33bc..2f11e0a13 100644
--- a/compiler/tflite2circle/driver/Driver.cpp
+++ b/compiler/tflite2circle/driver/Driver.cpp
@@ -24,10 +24,25 @@
#include "CircleModel.h"
#include "TFLModel.h"
+#include <vconone/vconone.h>
+
+void print_version(void)
+{
+ std::cout << "tflite2circle version " << vconone::get_string() << std::endl;
+ std::cout << vconone::get_copyright() << std::endl;
+}
+
int entry(int argc, char **argv)
{
arser::Arser arser{"tflite2circle is a Tensorflow lite to circle model converter"};
+ arser.add_argument("--version")
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("Show version information and exit")
+ .exit_with(print_version);
+
arser.add_argument("tflite")
.nargs(1)
.type(arser::DataType::STR)
@@ -42,7 +57,7 @@ int entry(int argc, char **argv)
{
std::cout << err.what() << std::endl;
std::cout << arser;
- return 0;
+ return 255;
}
std::string tfl_path = arser.get<std::string>("tflite");
diff --git a/compiler/tflite2circle/requires.cmake b/compiler/tflite2circle/requires.cmake
index ff19b7491..837c287b6 100644
--- a/compiler/tflite2circle/requires.cmake
+++ b/compiler/tflite2circle/requires.cmake
@@ -2,3 +2,4 @@ require("arser")
require("mio-tflite")
require("mio-circle")
require("safemain")
+require("vconone")
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions.h b/compiler/tflite2circle/src/BuildBuiltinOptions.h
index 159a8af97..00b3de943 100644
--- a/compiler/tflite2circle/src/BuildBuiltinOptions.h
+++ b/compiler/tflite2circle/src/BuildBuiltinOptions.h
@@ -62,10 +62,12 @@
#include "BuildBuiltinOptions/MirrorPadOptions.h"
#include "BuildBuiltinOptions/MulOptions.h"
#include "BuildBuiltinOptions/NegOptions.h"
+#include "BuildBuiltinOptions/NonMaxSuppressionV4Options.h"
#include "BuildBuiltinOptions/NotEqualOptions.h"
#include "BuildBuiltinOptions/OneHotOptions.h"
#include "BuildBuiltinOptions/PackOptions.h"
#include "BuildBuiltinOptions/PadOptions.h"
+#include "BuildBuiltinOptions/PadV2Options.h"
#include "BuildBuiltinOptions/RangeOptions.h"
#include "BuildBuiltinOptions/Pool2DOptions.h"
#include "BuildBuiltinOptions/PowOptions.h"
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/NonMaxSuppressionV4Options.cpp b/compiler/tflite2circle/src/BuildBuiltinOptions/NonMaxSuppressionV4Options.cpp
new file mode 100644
index 000000000..1a39f503b
--- /dev/null
+++ b/compiler/tflite2circle/src/BuildBuiltinOptions/NonMaxSuppressionV4Options.cpp
@@ -0,0 +1,30 @@
+/*
+ * 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 "NonMaxSuppressionV4Options.h"
+
+namespace tflite2circle
+{
+
+flatbuffers::Offset<circle::NonMaxSuppressionV4Options>
+build_circle_NonMaxSuppressionV4Options(flatbuffers::FlatBufferBuilder &fb,
+ const tflite::Operator *)
+{
+ circle::NonMaxSuppressionV4OptionsBuilder builtin_options_builder{fb};
+ return builtin_options_builder.Finish();
+}
+
+} // namespace tflite2circle
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/NonMaxSuppressionV4Options.h b/compiler/tflite2circle/src/BuildBuiltinOptions/NonMaxSuppressionV4Options.h
new file mode 100644
index 000000000..6073142a8
--- /dev/null
+++ b/compiler/tflite2circle/src/BuildBuiltinOptions/NonMaxSuppressionV4Options.h
@@ -0,0 +1,32 @@
+/*
+ * 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 __BBO_NON_MAX_SUPPRESSION_V4_OPTIONS_H__
+#define __BBO_NON_MAX_SUPPRESSION_V4_OPTIONS_H__
+
+#include <mio/tflite/schema_generated.h>
+#include <mio/circle/schema_generated.h>
+
+namespace tflite2circle
+{
+
+flatbuffers::Offset<circle::NonMaxSuppressionV4Options>
+build_circle_NonMaxSuppressionV4Options(flatbuffers::FlatBufferBuilder &fb,
+ const tflite::Operator *op);
+
+} // namespace tflite2circle
+
+#endif // __BBO_NON_MAX_SUPPRESSION_V4_OPTIONS_H__
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/PadV2Options.cpp b/compiler/tflite2circle/src/BuildBuiltinOptions/PadV2Options.cpp
new file mode 100644
index 000000000..6636634a3
--- /dev/null
+++ b/compiler/tflite2circle/src/BuildBuiltinOptions/PadV2Options.cpp
@@ -0,0 +1,29 @@
+/*
+ * 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 "PadV2Options.h"
+
+namespace tflite2circle
+{
+
+flatbuffers::Offset<circle::PadV2Options>
+build_circle_PadV2Options(flatbuffers::FlatBufferBuilder &fb, const tflite::Operator *op)
+{
+ circle::PadV2OptionsBuilder builtin_options_builder{fb};
+ return builtin_options_builder.Finish();
+}
+
+} // namespace tflite2circle
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/PadV2Options.h b/compiler/tflite2circle/src/BuildBuiltinOptions/PadV2Options.h
new file mode 100644
index 000000000..36a2c82e8
--- /dev/null
+++ b/compiler/tflite2circle/src/BuildBuiltinOptions/PadV2Options.h
@@ -0,0 +1,31 @@
+/*
+ * 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 __BBO_PADV2_OPTIONS_H__
+#define __BBO_PADV2_OPTIONS_H__
+
+#include <mio/tflite/schema_generated.h>
+#include <mio/circle/schema_generated.h>
+
+namespace tflite2circle
+{
+
+flatbuffers::Offset<circle::PadV2Options>
+build_circle_PadV2Options(flatbuffers::FlatBufferBuilder &fb, const tflite::Operator *op);
+
+} // namespace tflite2circle
+
+#endif // __BBO_PADV2_OPTIONS_H__
diff --git a/compiler/tflite2circle/src/TFLBuiltinOptions.lst b/compiler/tflite2circle/src/TFLBuiltinOptions.lst
index 3ef9f1575..a2a14538e 100644
--- a/compiler/tflite2circle/src/TFLBuiltinOptions.lst
+++ b/compiler/tflite2circle/src/TFLBuiltinOptions.lst
@@ -26,6 +26,7 @@ TFL_BUILTIN_OPTIONS(SpaceToDepthOptions)
//TFL_BUILTIN_OPTIONS(EmbeddingLookupSparseOptions)
TFL_BUILTIN_OPTIONS(MulOptions)
TFL_BUILTIN_OPTIONS(PadOptions)
+TFL_BUILTIN_OPTIONS(PadV2Options)
TFL_BUILTIN_OPTIONS(GatherOptions)
TFL_BUILTIN_OPTIONS(BatchToSpaceNDOptions)
TFL_BUILTIN_OPTIONS(SpaceToBatchNDOptions)
@@ -99,7 +100,7 @@ TFL_BUILTIN_OPTIONS(MatrixSetDiagOptions)
TFL_BUILTIN_OPTIONS(IfOptions)
TFL_BUILTIN_OPTIONS(WhileOptions)
TFL_BUILTIN_OPTIONS(DepthToSpaceOptions)
-//TFL_BUILTIN_OPTIONS(NonMaxSuppressionV4Options)
+TFL_BUILTIN_OPTIONS(NonMaxSuppressionV4Options)
//TFL_BUILTIN_OPTIONS(NonMaxSuppressionV5Options)
TFL_BUILTIN_OPTIONS(RankOptions)
TFL_BUILTIN_OPTIONS(ScatterNdOptions)
diff --git a/compiler/vconone/CMakeLists.txt b/compiler/vconone/CMakeLists.txt
new file mode 100644
index 000000000..b8cb79331
--- /dev/null
+++ b/compiler/vconone/CMakeLists.txt
@@ -0,0 +1,31 @@
+if (NOT VCONONE_VERSION)
+ set(VCONONE_VERSION 0x0000000000080001)
+ # 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
+endif()
+
+configure_file(version_cfg.h.in version_cfg.h @ONLY)
+
+set(DRIVER "driver/driver.cpp")
+
+file(GLOB_RECURSE SOURCES "src/*.cpp")
+file(GLOB_RECURSE TESTS "src/*.test.cpp")
+list(REMOVE_ITEM SOURCES ${TESTS})
+
+add_library(vconone STATIC ${SOURCES})
+target_include_directories(vconone PUBLIC include)
+target_include_directories(vconone PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
+
+add_executable(one-version ${DRIVER})
+target_link_libraries(one-version vconone)
+install(TARGETS one-version DESTINATION bin)
+
+if(NOT ENABLE_TEST)
+ return()
+endif(NOT ENABLE_TEST)
+
+nnas_find_package(GTest REQUIRED)
+
+GTest_AddTest(vconone_test ${TESTS})
+target_link_libraries(vconone_test vconone)
diff --git a/compiler/vconone/README.md b/compiler/vconone/README.md
new file mode 100644
index 000000000..c08dd63d3
--- /dev/null
+++ b/compiler/vconone/README.md
@@ -0,0 +1,14 @@
+# vconone
+
+_vconone_ provides version number and strings for one-* commands and command
+line tools
+
+# Revise version number
+
+To revise version number, update `VCONONE_VERSION` in `CmakeLists.txt`
+or give `-DVCONONE_VERSION=0x0000000100080001` at cmake configure step.
+
+Number given is four numbers `build`, `patch`, `minor` and `major` in order for
+each 16bit integers. `build` is not used for now.
+
+`0x0000000100080001` version is interpretered as `1.8.1`
diff --git a/compiler/vconone/driver/driver.cpp b/compiler/vconone/driver/driver.cpp
new file mode 100644
index 000000000..12bd0eef2
--- /dev/null
+++ b/compiler/vconone/driver/driver.cpp
@@ -0,0 +1,36 @@
+/*
+ * 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 <vconone/vconone.h>
+
+#include <string>
+#include <iostream>
+
+int main(int argc, char *argv[])
+{
+ auto str = vconone::get_string();
+ if (argc >= 2)
+ {
+ for (int c = 1; c < argc; ++c)
+ std::cout << argv[c] << " ";
+ std::cout << "version " << str << std::endl;
+ std::cout << vconone::get_copyright() << std::endl;
+ }
+ else
+ std::cout << str;
+
+ return 0;
+}
diff --git a/compiler/vconone/include/vconone/vconone.h b/compiler/vconone/include/vconone/vconone.h
new file mode 100644
index 000000000..a6a1998a5
--- /dev/null
+++ b/compiler/vconone/include/vconone/vconone.h
@@ -0,0 +1,61 @@
+/*
+ * 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 __VCON_ONE_H__
+#define __VCON_ONE_H__
+
+#include <cstdint>
+#include <string>
+
+namespace vconone
+{
+
+struct four
+{
+ uint16_t major;
+ uint16_t minor;
+ uint16_t patch;
+ uint16_t build; // build is not used for now
+};
+
+union version {
+ uint64_t v;
+ four f;
+};
+
+/**
+ * @brief get_number will return version union structure
+ */
+version get_number(void);
+
+/**
+ * @brief get_string will return string of major.minor.patch (without build)
+ */
+std::string get_string(void);
+
+/**
+ * @brief get_string4 will return string of major.minor.patch.build
+ */
+std::string get_string4(void);
+
+/**
+ * @brief get_copyright will return copyright string
+ */
+std::string get_copyright(void);
+
+} // namespace vconone
+
+#endif // __VCON_ONE_H__
diff --git a/compiler/vconone/src/version.cpp b/compiler/vconone/src/version.cpp
new file mode 100644
index 000000000..9b693c621
--- /dev/null
+++ b/compiler/vconone/src/version.cpp
@@ -0,0 +1,63 @@
+/*
+ * 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 "vconone/vconone.h"
+
+#include "version_cfg.h"
+
+#include <sstream>
+
+namespace vconone
+{
+
+version get_number(void)
+{
+ version v;
+ v.v = VCONONE_VERSION;
+ return v;
+}
+
+std::string get_string4(void)
+{
+ std::ostringstream ss;
+
+ auto v = get_number();
+ ss << unsigned(v.f.major) << "." << unsigned(v.f.minor) << "." << unsigned(v.f.patch) << "."
+ << unsigned(v.f.build);
+
+ return ss.str();
+}
+
+std::string get_string(void)
+{
+ std::ostringstream ss;
+
+ auto v = get_number();
+ ss << unsigned(v.f.major) << "." << unsigned(v.f.minor) << "." << unsigned(v.f.patch);
+
+ return ss.str();
+}
+
+std::string get_copyright(void)
+{
+ std::string str;
+ str = "Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved\r\n";
+ str += "Licensed under the Apache License, Version 2.0\r\n";
+ str += "https://github.com/Samsung/ONE";
+ return str;
+}
+
+} // namespace vconone
diff --git a/compiler/vconone/src/version.test.cpp b/compiler/vconone/src/version.test.cpp
new file mode 100644
index 000000000..35a0647c1
--- /dev/null
+++ b/compiler/vconone/src/version.test.cpp
@@ -0,0 +1,49 @@
+/*
+ * 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 <vconone/vconone.h>
+
+#include <gtest/gtest.h>
+
+TEST(vconone, version_number)
+{
+ auto v = vconone::get_number();
+
+ ASSERT_NE(0x0000000000000000ULL, v.v);
+}
+
+TEST(vconone, version_string)
+{
+ auto str = vconone::get_string();
+
+ ASSERT_NE("..", str);
+ ASSERT_NE("", str);
+}
+
+TEST(vconone, version_string4)
+{
+ auto str = vconone::get_string4();
+
+ ASSERT_NE("...", str);
+ ASSERT_NE("", str);
+}
+
+TEST(vconone, copyright)
+{
+ auto str = vconone::get_copyright();
+
+ ASSERT_NE("", str);
+}
diff --git a/compiler/vconone/version_cfg.h.in b/compiler/vconone/version_cfg.h.in
new file mode 100644
index 000000000..aa3ad9e70
--- /dev/null
+++ b/compiler/vconone/version_cfg.h.in
@@ -0,0 +1,22 @@
+/*
+ * 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 __VCON_ONE_VERSION_CFG_H__
+#define __VCON_ONE_VERSION_CFG_H__
+
+#define VCONONE_VERSION @VCONONE_VERSION@ULL
+
+#endif // __VCON_ONE_VERSION_CFG_H__