diff options
Diffstat (limited to 'compiler/mio-circle05/src')
-rw-r--r-- | compiler/mio-circle05/src/Helper.cpp | 110 | ||||
-rw-r--r-- | compiler/mio-circle05/src/Helper.test.cpp | 153 | ||||
-rw-r--r-- | compiler/mio-circle05/src/Reader.cpp | 147 | ||||
-rw-r--r-- | compiler/mio-circle05/src/Reader.test.cpp | 60 |
4 files changed, 470 insertions, 0 deletions
diff --git a/compiler/mio-circle05/src/Helper.cpp b/compiler/mio-circle05/src/Helper.cpp new file mode 100644 index 000000000..bbfa2041a --- /dev/null +++ b/compiler/mio-circle05/src/Helper.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mio_circle/Helper.h" + +#include <algorithm> +#include <sstream> + +namespace mio +{ +namespace circle +{ + +/** + * This will provide v3/v3a/v3b format neutral BuiltinOperator + * NOTE circle has minus value opcode (252~254 as uint8_t) + * we cannot use std::max() like tflite as deprecated_builtin_code can be + * minus and builtin_code being 0 for v0.3 files. + */ +::circle::BuiltinOperator builtin_code_neutral(const ::circle::OperatorCode *opcode) +{ + assert(opcode != nullptr); + if (opcode->deprecated_builtin_code() == 127) + { + assert(opcode->builtin_code() >= 127); + return opcode->builtin_code(); + } + // There was no 255(-1) value in v0.3 + assert(opcode->deprecated_builtin_code() != -1); + return static_cast<::circle::BuiltinOperator>(opcode->deprecated_builtin_code()); +} + +bool is_valid(const ::circle::OperatorCode *opcode) +{ + // Valid Range : BuiltinOperator_MIN <= deprecated_builtin_code <= 127 + const int8_t deprecated_builtin_code = opcode->deprecated_builtin_code(); + if (deprecated_builtin_code < ::circle::BuiltinOperator_MIN) + return false; + // There was no 255(-1) value in v0.3 + if (deprecated_builtin_code == -1) + return false; + + const ::circle::BuiltinOperator builtin_code = opcode->builtin_code(); + if (!(::circle::BuiltinOperator_MIN <= builtin_code && + builtin_code <= ::circle::BuiltinOperator_MAX)) + return false; + + return true; +} + +bool is_custom(const ::circle::OperatorCode *opcode) +{ + ::circle::BuiltinOperator code = builtin_code_neutral(opcode); + return (code == ::circle::BuiltinOperator_CUSTOM); +} + +std::string opcode_name(const ::circle::OperatorCode *opcode) +{ + assert(opcode); + + if (!is_valid(opcode)) + { + std::ostringstream oss; + oss << "(invalid)"; + return oss.str(); + } + + if (is_custom(opcode)) + { + if (!opcode->custom_code()) + return "(invalid custom)"; + + std::string custom_op = "CUSTOM("; + custom_op += opcode->custom_code()->c_str(); + custom_op += ")"; + return custom_op; + } + + ::circle::BuiltinOperator code = builtin_code_neutral(opcode); + return ::circle::EnumNameBuiltinOperator(code); +} + +const char *tensor_type(const ::circle::Tensor *tensor) +{ + return ::circle::EnumNameTensorType(tensor->type()); +} + +const char *tensor_name(const ::circle::Tensor *tensor) +{ + if (tensor->name() == nullptr || std::string(tensor->name()->c_str()).empty()) + return "(noname)"; + + return tensor->name()->c_str(); +} + +} // namespace circle +} // namespace mio diff --git a/compiler/mio-circle05/src/Helper.test.cpp b/compiler/mio-circle05/src/Helper.test.cpp new file mode 100644 index 000000000..be63688df --- /dev/null +++ b/compiler/mio-circle05/src/Helper.test.cpp @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mio_circle/Helper.h" + +#include <flatbuffers/flatbuffers.h> +#include <gtest/gtest.h> + +#include <vector> + +class mio_circle05_helper_test : public ::testing::Test +{ +protected: + void initialization_finish(void) + { + _fbb.Finish(circle::CreateModelDirect(_fbb, 0, &_opcodes_vec)); + } + +protected: + void add_operator_code(int8_t deprecated_builtin_code, const char *custom_code, + circle::BuiltinOperator builtin_code) + { + _opcodes_vec.push_back(circle::CreateOperatorCodeDirect( + _fbb, deprecated_builtin_code, custom_code, 1 /* version */, builtin_code)); + } + + const circle::OperatorCode *get_operator_code(uint8_t idx) + { + return circle::GetModel(_fbb.GetBufferPointer())->operator_codes()->Get(idx); + } + +private: + flatbuffers::FlatBufferBuilder _fbb; + std::vector<flatbuffers::Offset<circle::OperatorCode>> _opcodes_vec; +}; + +TEST_F(mio_circle05_helper_test, v05) +{ + // BuiltinOperator_ADD = 0 + // BuiltinOperator_CONV_2D = 3 + add_operator_code(3, "", circle::BuiltinOperator_ADD); + initialization_finish(); + + ASSERT_TRUE(mio::circle::is_valid(get_operator_code(0))); + ASSERT_EQ(mio::circle::builtin_code_neutral(get_operator_code(0)), + circle::BuiltinOperator_CONV_2D); + ASSERT_FALSE(mio::circle::is_custom(get_operator_code(0))); +} + +TEST_F(mio_circle05_helper_test, v05_custom_old) +{ + // BuiltinOperator_ADD = 0 + // BuiltinOperator_CUSTOM = 32 + add_operator_code(32, "custom", circle::BuiltinOperator_ADD); + initialization_finish(); + + ASSERT_TRUE(mio::circle::is_valid(get_operator_code(0))); + ASSERT_EQ(mio::circle::builtin_code_neutral(get_operator_code(0)), + circle::BuiltinOperator_CUSTOM); + ASSERT_TRUE(mio::circle::is_custom(get_operator_code(0))); +} + +TEST_F(mio_circle05_helper_test, v05_NEG) +{ + // BuiltinOperator_ADD = 0 + // BuiltinOperator_CUMSUM = 128 + // deprecated_builtin_code cannot be negative value + add_operator_code(128, "", circle::BuiltinOperator_ADD); + initialization_finish(); + + ASSERT_FALSE(mio::circle::is_valid(get_operator_code(0))); +} + +TEST_F(mio_circle05_helper_test, v05_under127) +{ + // BuiltinOperator_CONV_2D = 3 + add_operator_code(3, "", circle::BuiltinOperator_CONV_2D); + initialization_finish(); + + ASSERT_TRUE(mio::circle::is_valid(get_operator_code(0))); + ASSERT_EQ(mio::circle::builtin_code_neutral(get_operator_code(0)), + circle::BuiltinOperator_CONV_2D); + ASSERT_FALSE(mio::circle::is_custom(get_operator_code(0))); +} + +TEST_F(mio_circle05_helper_test, v05_under127_NEG) +{ + // BuiltinOperator_CONV_2D = 3 + // BuiltinOperator_CUMSUM = 128 + // deprecated_builtin_code cannot be negative value + add_operator_code(128, "", circle::BuiltinOperator_CONV_2D); + initialization_finish(); + + ASSERT_FALSE(mio::circle::is_valid(get_operator_code(0))); +} + +TEST_F(mio_circle05_helper_test, v05_custom) +{ + // BuiltinOperator_CUSTOM = 32 + add_operator_code(32, "custom", circle::BuiltinOperator_CUSTOM); + initialization_finish(); + + ASSERT_TRUE(mio::circle::is_valid(get_operator_code(0))); + ASSERT_EQ(mio::circle::builtin_code_neutral(get_operator_code(0)), + circle::BuiltinOperator_CUSTOM); + ASSERT_TRUE(mio::circle::is_custom(get_operator_code(0))); +} + +TEST_F(mio_circle05_helper_test, v05_custom_NEG) +{ + // BuiltinOperator_CUMSUM = 128 + // deprecated_builtin_code cannot be negative value + add_operator_code(128, "custom", circle::BuiltinOperator_CUSTOM); + initialization_finish(); + + ASSERT_FALSE(mio::circle::is_valid(get_operator_code(0))); +} + +TEST_F(mio_circle05_helper_test, v05_over127) +{ + // BuiltinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES = 127 + // BuiltinOperator_CUMSUM = 128 + add_operator_code(127, "", circle::BuiltinOperator_CUMSUM); + initialization_finish(); + + ASSERT_TRUE(mio::circle::is_valid(get_operator_code(0))); + ASSERT_EQ(mio::circle::builtin_code_neutral(get_operator_code(0)), + circle::BuiltinOperator_CUMSUM); + ASSERT_FALSE(mio::circle::is_custom(get_operator_code(0))); +} + +TEST_F(mio_circle05_helper_test, v05_over127_NEG) +{ + // BuiltinOperator_CUMSUM = 128 + // deprecated_builtin_code cannot be negative value + add_operator_code(128, "", circle::BuiltinOperator_CUMSUM); + initialization_finish(); + + ASSERT_FALSE(mio::circle::is_valid(get_operator_code(0))); +} diff --git a/compiler/mio-circle05/src/Reader.cpp b/compiler/mio-circle05/src/Reader.cpp new file mode 100644 index 000000000..0ee22db14 --- /dev/null +++ b/compiler/mio-circle05/src/Reader.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mio_circle/Reader.h" +#include "mio_circle/Helper.h" + +#include <sstream> +#include <string> + +namespace mio +{ +namespace circle +{ + +Reader::Reader(const ::circle::Model *model) +{ + if (model == nullptr) + { + throw std::runtime_error("Invalid model"); + } + + _version = model->version(); + _subgraphs = model->subgraphs(); + _buffers = model->buffers(); + _metadata = model->metadata(); + _signature_defs = model->signature_defs(); + + auto opcodes = model->operator_codes(); + for (const ::circle::OperatorCode *opcode : *opcodes) + { + _op_codes.push_back(opcode); + } +} + +size_t Reader::buffer_info(uint32_t buf_idx, const uint8_t **buff_data) +{ + if (buff_data != nullptr) + { + *buff_data = nullptr; + } + + if (buf_idx == 0) + return 0; + + if (auto *buffer = (*_buffers)[buf_idx]) + { + if (auto *array = buffer->data()) + { + if (size_t size = array->size()) + { + if (buff_data != nullptr) + { + *buff_data = reinterpret_cast<const uint8_t *>(array->data()); + } + return size; + } + } + } + + return 0; +} + +::circle::BuiltinOperator Reader::builtin_code(const ::circle::Operator *op) const +{ + uint32_t index = op->opcode_index(); + assert(index < _op_codes.size()); + const ::circle::OperatorCode *opcode = _op_codes.at(index); + + return mio::circle::builtin_code_neutral(opcode); +} + +std::string Reader::opcode_name(const ::circle::Operator *op) const +{ + uint32_t index = op->opcode_index(); + assert(index < _op_codes.size()); + const ::circle::OperatorCode *opcode = _op_codes.at(index); + + if (!mio::circle::is_valid(opcode)) + { + std::ostringstream oss; + oss << "(invalid: " << index << ")"; + return oss.str(); + } + + return mio::circle::opcode_name(opcode); +} + +std::vector<int32_t> Reader::outputs(const ::circle::Operator *op) const +{ + return as_index_vector(op->outputs()); +} + +std::string Reader::tensor_name(const ::circle::Tensor *tensor) const +{ + return mio::circle::tensor_name(tensor); +} + +std::string Reader::tensor_dtype(const ::circle::Tensor *tensor) const +{ + return mio::circle::tensor_type(tensor); +} + +bool Reader::select_subgraph(uint32_t sgindex) +{ + _subgraph_index = sgindex; + _tensors = nullptr; + _operators = nullptr; + + _inputs.clear(); + _outputs.clear(); + + if (_subgraphs->Length() <= sgindex) + { + assert(false); + return false; + } + + const ::circle::SubGraph *subgraph = (*_subgraphs)[sgindex]; + + auto name = subgraph->name(); + _subgraph_name = name ? name->c_str() : "(noname)"; + + _tensors = subgraph->tensors(); + _operators = subgraph->operators(); + _data_format = subgraph->data_format(); + + _inputs = as_index_vector(subgraph->inputs()); + _outputs = as_index_vector(subgraph->outputs()); + + return true; +} + +} // namespace circle +} // namespace mio diff --git a/compiler/mio-circle05/src/Reader.test.cpp b/compiler/mio-circle05/src/Reader.test.cpp new file mode 100644 index 000000000..0c60999f4 --- /dev/null +++ b/compiler/mio-circle05/src/Reader.test.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mio_circle/Reader.h" + +#include <flatbuffers/flatbuffers.h> +#include <gtest/gtest.h> + +class mio_circle05_reader_test : public ::testing::Test +{ +protected: + void initialization_emty(void) + { + _model = circle::CreateModelDirect(_fbb, 0, &_opcodes_vec); + circle::FinishModelBuffer(_fbb, _model); + } + + const circle::Model *circleModel(void) + { + auto ptr = _fbb.GetBufferPointer(); + return circle::GetModel(ptr); + } + +private: + flatbuffers::FlatBufferBuilder _fbb; + flatbuffers::Offset<circle::Model> _model; + std::vector<flatbuffers::Offset<circle::OperatorCode>> _opcodes_vec; +}; + +TEST_F(mio_circle05_reader_test, null_Model_NEG) +{ + EXPECT_THROW(mio::circle::Reader reader(nullptr), std::runtime_error); +} + +TEST_F(mio_circle05_reader_test, empty_Model) +{ + initialization_emty(); + + const circle::Model *model = circleModel(); + EXPECT_NE(nullptr, model); + + mio::circle::Reader reader(model); + + SUCCEED(); +} + +// TODO add more tests |