From 502d86b1a69e015efdfa90aec84f6b6c4682c31c Mon Sep 17 00:00:00 2001 From: Sergei Barannikov/AI Tools Lab /SRR/Engineer/Samsung Electronics Date: Fri, 6 Dec 2019 12:21:35 +0300 Subject: [PATCH] [neurun] Move DataType.h into ir directory (#9389) * Move `DataType.h` in `ir` directory. * Move `DataType` to `neurun::ir` namespace. Signed-off-by: Sergei Barannikov --- runtime/neurun/api/src/CustomKernel.cc | 8 ++++---- runtime/neurun/api/src/nnfw_api_internal.cc | 4 ++-- runtime/neurun/backend/acl_cl/KernelGenerator.cc | 6 +++--- runtime/neurun/backend/acl_cl/ShapeFixer.cc | 1 - runtime/neurun/backend/acl_common/Convert.cc | 14 +++++++------- runtime/neurun/backend/acl_common/Convert.h | 2 +- runtime/neurun/backend/acl_neon/KernelGenerator.cc | 4 ++-- runtime/neurun/backend/acl_neon/ShapeFixer.cc | 1 - runtime/neurun/backend/cpu/ShapeFixer.cc | 8 ++++---- runtime/neurun/backend/cpu/kernel/OperationUtils.h | 4 ++-- runtime/neurun/backend/cpu/kernel/PermuteLayer.cc | 4 ++-- runtime/neurun/backend/cpu/kernel/PermuteLayer.h | 4 ++-- runtime/neurun/backend/cpu/operand/Tensor.h | 2 +- runtime/neurun/backend/srcn/ConstantInitializer.cc | 2 +- runtime/neurun/backend/srcn/Convert.cc | 2 +- runtime/neurun/backend/srcn/kernel/OperationUtils.h | 4 ++-- runtime/neurun/backend/srcn/operand/Tensor.h | 2 +- .../neurun/core/include/backend/CustomKernelBuilder.h | 4 ++-- .../neurun/core/include/backend/IConstantInitializer.h | 4 ++-- runtime/neurun/core/include/{model => ir}/DataType.h | 14 ++++++++++---- runtime/neurun/core/include/model/Operand.h | 4 ++-- runtime/neurun/core/include/model/OperandInfo.h | 2 +- runtime/neurun/core/include/model/TypeInfo.h | 4 ++-- runtime/neurun/core/include/model/operation/Permute.h | 6 +++--- runtime/neurun/core/src/compiler/HEScheduler.cc | 6 +++--- runtime/neurun/core/src/compiler/OperationValidator.cc | 16 ++++++++-------- runtime/neurun/core/src/exec/ExecutionObservers.cc | 2 +- runtime/neurun/core/src/exec/ExecutorBase.cc | 4 ++-- runtime/neurun/core/src/exec/interp/Tensor.h | 6 +++--- runtime/neurun/core/src/exec/interp/operations/Add.cc | 4 ++-- .../core/src/exec/interp/operations/AvgPool2D.cc | 2 +- .../neurun/core/src/exec/interp/operations/Concat.cc | 2 +- .../neurun/core/src/exec/interp/operations/Conv2D.cc | 2 +- .../core/src/exec/interp/operations/DepthwiseConv.cc | 2 +- .../core/src/exec/interp/operations/FullyConnected.cc | 2 +- .../core/src/exec/interp/operations/MaxPool2D.cc | 2 +- .../neurun/core/src/exec/interp/operations/SoftMax.cc | 2 +- runtime/neurun/core/src/model/operation/Permute.cc | 3 +-- runtime/neurun/frontend/base_loader/base_loader.h | 18 +++++++----------- runtime/neurun/frontend/nnapi/wrapper/NNAPIConvert.h | 5 +---- .../neurun/frontend/nnapi/wrapper/OperationFactory.cc | 2 +- runtime/neurun/test/core/compiler/Scheduler.cc | 2 +- runtime/neurun/test/core/exec/ExecInstance.cc | 2 +- runtime/neurun/test/core/exec/interp/ExecManager.cc | 2 +- runtime/neurun/test/graph/operand/Set.cc | 2 +- runtime/neurun/test/graph/operand/UseDef.cc | 2 +- runtime/neurun/test/graph/operation/SetIO.cc | 4 ++-- runtime/neurun/test/graph/verifier/Verifier.cc | 2 +- 48 files changed, 101 insertions(+), 105 deletions(-) rename runtime/neurun/core/include/{model => ir}/DataType.h (84%) diff --git a/runtime/neurun/api/src/CustomKernel.cc b/runtime/neurun/api/src/CustomKernel.cc index dcf6c52..60ddeed 100644 --- a/runtime/neurun/api/src/CustomKernel.cc +++ b/runtime/neurun/api/src/CustomKernel.cc @@ -45,16 +45,16 @@ public: switch (type.dtype) { - case model::DataType::FLOAT32: + case ir::DataType::FLOAT32: api_type.dtype = NNFW_TYPE_TENSOR_FLOAT32; break; - case model::DataType::INT32: + case ir::DataType::INT32: api_type.dtype = NNFW_TYPE_TENSOR_INT32; break; - case model::DataType::QUANT8_ASYMM: + case ir::DataType::QUANT8_ASYMM: api_type.dtype = NNFW_TYPE_TENSOR_QUANT8_ASYMM; break; - case model::DataType::BOOL8: + case ir::DataType::BOOL8: api_type.dtype = NNFW_TYPE_TENSOR_BOOL; break; default: diff --git a/runtime/neurun/api/src/nnfw_api_internal.cc b/runtime/neurun/api/src/nnfw_api_internal.cc index 574f844..dcf14a2 100644 --- a/runtime/neurun/api/src/nnfw_api_internal.cc +++ b/runtime/neurun/api/src/nnfw_api_internal.cc @@ -276,9 +276,9 @@ NNFW_STATUS nnfw_session::set_output_layout(uint32_t index, NNFW_LAYOUT layout) return NNFW_STATUS_NO_ERROR; } -static NNFW_TYPE datatype_to_nnfw_dtype(neurun::model::DataType dt) +static NNFW_TYPE datatype_to_nnfw_dtype(neurun::ir::DataType dt) { - using neurun::model::DataType; + using neurun::ir::DataType; switch (dt) { case DataType::FLOAT32: diff --git a/runtime/neurun/backend/acl_cl/KernelGenerator.cc b/runtime/neurun/backend/acl_cl/KernelGenerator.cc index 08d77c8..a8e4e0b 100644 --- a/runtime/neurun/backend/acl_cl/KernelGenerator.cc +++ b/runtime/neurun/backend/acl_cl/KernelGenerator.cc @@ -25,7 +25,7 @@ #include "kernel/ConcatLayer.h" #include "model/Index.h" -#include "model/DataType.h" +#include "ir/DataType.h" #include "model/InternalType.h" #include "compiler/IExecutionBuilder.h" #include "exec/NopFunction.h" @@ -666,7 +666,7 @@ void KernelGenerator::visit(const model::operation::StridedSlice &node) const int endData_size = _ctx.at(ends_index).shape().num_elements(); const int stridesData_size = _ctx.at(strides_index).shape().num_elements(); - using neurun::model::DataType; + using ir::DataType; UNUSED_RELEASE(startData_size); UNUSED_RELEASE(endData_size); @@ -1369,7 +1369,7 @@ void KernelGenerator::visit(const model::operation::SpaceToBatchND &node) assert(_ctx.at(paddings_index).isConstant()); std::unique_ptr<::arm_compute::IFunction> fn; - if (_ctx.at(ofm_index).typeInfo().type() == model::DataType::QUANT8_ASYMM) + if (_ctx.at(ofm_index).typeInfo().type() == ir::DataType::QUANT8_ASYMM) { // NOTE CLSpaceToBatchLayer has a bug that padding's values are 0 even when zero point of // QASYMM8 is not 0. diff --git a/runtime/neurun/backend/acl_cl/ShapeFixer.cc b/runtime/neurun/backend/acl_cl/ShapeFixer.cc index d8a8035..2448e2e 100644 --- a/runtime/neurun/backend/acl_cl/ShapeFixer.cc +++ b/runtime/neurun/backend/acl_cl/ShapeFixer.cc @@ -25,7 +25,6 @@ #include "kernel/ConcatLayer.h" #include "model/Index.h" -#include "model/DataType.h" #include "model/InternalType.h" #include "compiler/IExecutionBuilder.h" #include "exec/NopFunction.h" diff --git a/runtime/neurun/backend/acl_common/Convert.cc b/runtime/neurun/backend/acl_common/Convert.cc index 6d1bc72..ed8258b 100644 --- a/runtime/neurun/backend/acl_common/Convert.cc +++ b/runtime/neurun/backend/acl_common/Convert.cc @@ -17,7 +17,7 @@ #include "Convert.h" #include "Swizzle.h" -#include "model/DataType.h" +#include "ir/DataType.h" #include namespace @@ -88,19 +88,19 @@ namespace acl_common return res; } -::arm_compute::DataType asDataType(const ::neurun::model::DataType &type) +::arm_compute::DataType asDataType(const ir::DataType type) { switch (type) { - case ::neurun::model::DataType::FLOAT32: + case ir::DataType::FLOAT32: return ::arm_compute::DataType::F32; - case ::neurun::model::DataType::INT32: + case ir::DataType::INT32: return ::arm_compute::DataType::S32; - case ::neurun::model::DataType::UINT32: + case ir::DataType::UINT32: return ::arm_compute::DataType::U32; - case ::neurun::model::DataType::QUANT8_ASYMM: + case ir::DataType::QUANT8_ASYMM: return ::arm_compute::DataType::QASYMM8; - case ::neurun::model::DataType::BOOL8: + case ir::DataType::BOOL8: return ::arm_compute::DataType::U8; default: throw std::runtime_error("Not supported, yet"); diff --git a/runtime/neurun/backend/acl_common/Convert.h b/runtime/neurun/backend/acl_common/Convert.h index 81bfc6e..66d4405 100644 --- a/runtime/neurun/backend/acl_common/Convert.h +++ b/runtime/neurun/backend/acl_common/Convert.h @@ -47,7 +47,7 @@ namespace acl_common ::arm_compute::Coordinates asTensorCoordinate(const ::neurun::util::Coordinates &coord, ir::Layout frontend_layout, ir::Layout backend_layout); -::arm_compute::DataType asDataType(const ::neurun::model::DataType &type); +::arm_compute::DataType asDataType(ir::DataType type); ::arm_compute::TensorInfo asTensorInfo(const ::neurun::model::Shape &shape, const ::neurun::model::TypeInfo &typeInfo, ir::Layout frontend_layout, ir::Layout backend_layout, diff --git a/runtime/neurun/backend/acl_neon/KernelGenerator.cc b/runtime/neurun/backend/acl_neon/KernelGenerator.cc index 2e3b51c..ea03b9e 100644 --- a/runtime/neurun/backend/acl_neon/KernelGenerator.cc +++ b/runtime/neurun/backend/acl_neon/KernelGenerator.cc @@ -25,7 +25,7 @@ #include "kernel/ConcatLayer.h" #include "util/Padding.h" #include "model/Index.h" -#include "model/DataType.h" +#include "ir/DataType.h" #include "model/InternalType.h" #include "compiler/IExecutionBuilder.h" #include "exec/NopFunction.h" @@ -1767,7 +1767,7 @@ void KernelGenerator::visit(const model::operation::StridedSlice &node) const int endData_size = _ctx.at(ends_index).shape().num_elements(); const int stridesData_size = _ctx.at(strides_index).shape().num_elements(); - using neurun::model::DataType; + using ir::DataType; UNUSED_RELEASE(startData_size); UNUSED_RELEASE(endData_size); diff --git a/runtime/neurun/backend/acl_neon/ShapeFixer.cc b/runtime/neurun/backend/acl_neon/ShapeFixer.cc index d6dbf17..3d69d8f 100644 --- a/runtime/neurun/backend/acl_neon/ShapeFixer.cc +++ b/runtime/neurun/backend/acl_neon/ShapeFixer.cc @@ -34,7 +34,6 @@ #include "kernel/ConcatLayer.h" #include "util/Padding.h" #include "model/Index.h" -#include "model/DataType.h" #include "model/InternalType.h" #include "compiler/IExecutionBuilder.h" #include "exec/NopFunction.h" diff --git a/runtime/neurun/backend/cpu/ShapeFixer.cc b/runtime/neurun/backend/cpu/ShapeFixer.cc index d874138..679d2cd 100644 --- a/runtime/neurun/backend/cpu/ShapeFixer.cc +++ b/runtime/neurun/backend/cpu/ShapeFixer.cc @@ -83,7 +83,7 @@ void ShapeFixer::visit(const model::operation::Add &node) const auto rhs_index{node.getInputs().at(model::operation::Add::Input::RHS)}; // Quantization : not supported - if (_ctx.at(lhs_index).typeInfo().type() == model::DataType::QUANT8_ASYMM) + if (_ctx.at(lhs_index).typeInfo().type() == ir::DataType::QUANT8_ASYMM) { throw std::runtime_error{"ShapeFixer: NYI for quantized Add"}; } @@ -107,7 +107,7 @@ void ShapeFixer::visit(const model::operation::Sub &node) const auto rhs_index{node.getInputs().at(model::operation::Sub::Input::RHS)}; // Quantization : not supported - if (_ctx.at(lhs_index).typeInfo().type() == model::DataType::QUANT8_ASYMM) + if (_ctx.at(lhs_index).typeInfo().type() == ir::DataType::QUANT8_ASYMM) { throw std::runtime_error{"ShapeFixer: NYI for quantized Sub"}; } @@ -129,7 +129,7 @@ void ShapeFixer::visit(const model::operation::Mul &node) const auto rhs_index{node.getInputs().at(model::operation::Sub::Input::RHS)}; // Quantization : not supported - if (_ctx.at(lhs_index).typeInfo().type() == model::DataType::QUANT8_ASYMM) + if (_ctx.at(lhs_index).typeInfo().type() == ir::DataType::QUANT8_ASYMM) { throw std::runtime_error{"ShapeFixer: NYI for quantized Mul"}; } @@ -155,7 +155,7 @@ void ShapeFixer::visit(const model::operation::Pad &node) const auto lhs_index{node.getInputs().at(model::operation::Sub::Input::LHS)}; // Quantization : not supported - if (_ctx.at(lhs_index).typeInfo().type() == model::DataType::QUANT8_ASYMM) + if (_ctx.at(lhs_index).typeInfo().type() == ir::DataType::QUANT8_ASYMM) { throw std::runtime_error{"ShapeFixer: NYI for quantized Pad"}; } diff --git a/runtime/neurun/backend/cpu/kernel/OperationUtils.h b/runtime/neurun/backend/cpu/kernel/OperationUtils.h index b8765a5..c466f9f 100644 --- a/runtime/neurun/backend/cpu/kernel/OperationUtils.h +++ b/runtime/neurun/backend/cpu/kernel/OperationUtils.h @@ -24,10 +24,10 @@ #include #include "model/Operand.h" -#include "model/DataType.h" +#include "ir/DataType.h" #include -using OperandType = neurun::model::DataType; +using OperandType = neurun::ir::DataType; namespace neurun { diff --git a/runtime/neurun/backend/cpu/kernel/PermuteLayer.cc b/runtime/neurun/backend/cpu/kernel/PermuteLayer.cc index 1520f99..fc758cf 100644 --- a/runtime/neurun/backend/cpu/kernel/PermuteLayer.cc +++ b/runtime/neurun/backend/cpu/kernel/PermuteLayer.cc @@ -29,7 +29,7 @@ using Type = model::operation::Permute::Type; void PermuteLayer::configure(std::shared_ptr input, std::shared_ptr output, - const model::Shape &output_shape, Type type, model::DataType dataType) + const model::Shape &output_shape, Type type, ir::DataType dataType) { _input = input; _output = output; @@ -40,7 +40,7 @@ void PermuteLayer::configure(std::shared_ptr input, void PermuteLayer::run() { - using ::neurun::model::DataType; + using ir::DataType; switch (_dataType) { case DataType::FLOAT32: diff --git a/runtime/neurun/backend/cpu/kernel/PermuteLayer.h b/runtime/neurun/backend/cpu/kernel/PermuteLayer.h index 2c7113e..3fec953 100644 --- a/runtime/neurun/backend/cpu/kernel/PermuteLayer.h +++ b/runtime/neurun/backend/cpu/kernel/PermuteLayer.h @@ -45,7 +45,7 @@ public: void configure(std::shared_ptr input, std::shared_ptr output, const model::Shape &output_shape, model::operation::Permute::Type type, - model::DataType dataType); + ir::DataType dataType); void run(); void runSync() { @@ -199,7 +199,7 @@ private: std::shared_ptr _output{nullptr}; model::Shape _output_shape{}; model::operation::Permute::Type _type{model::operation::Permute::Type::COPY}; - model::DataType _dataType{model::DataType::FLOAT32}; + ir::DataType _dataType{ir::DataType::FLOAT32}; }; } // namespace kernel diff --git a/runtime/neurun/backend/cpu/operand/Tensor.h b/runtime/neurun/backend/cpu/operand/Tensor.h index 7d83cda..ef0579f 100644 --- a/runtime/neurun/backend/cpu/operand/Tensor.h +++ b/runtime/neurun/backend/cpu/operand/Tensor.h @@ -42,7 +42,7 @@ public: public: void setBuffer(uint8_t *buffer) { _buffer = buffer; } - ::neurun::model::DataType data_type() const { return _info.typeInfo().type(); } + ir::DataType data_type() const { return _info.typeInfo().type(); } public: uint8_t *buffer() const override { return _buffer; } diff --git a/runtime/neurun/backend/srcn/ConstantInitializer.cc b/runtime/neurun/backend/srcn/ConstantInitializer.cc index 549248b..3260d54 100644 --- a/runtime/neurun/backend/srcn/ConstantInitializer.cc +++ b/runtime/neurun/backend/srcn/ConstantInitializer.cc @@ -99,7 +99,7 @@ void ConstantInitializer::registerPermuteKernelInitializer(const model::OperandI VERBOSE(FillOperandData) << "[SRCN] Fill data for operand " << index.value() << std::endl; const auto type = obj.typeInfo().type(); - using neurun::model::DataType; + using ir::DataType; using namespace std::placeholders; switch (type) diff --git a/runtime/neurun/backend/srcn/Convert.cc b/runtime/neurun/backend/srcn/Convert.cc index 0e347a1..267f62b 100644 --- a/runtime/neurun/backend/srcn/Convert.cc +++ b/runtime/neurun/backend/srcn/Convert.cc @@ -18,7 +18,7 @@ #include #include -#include +#include #include "Swizzle.h" #include diff --git a/runtime/neurun/backend/srcn/kernel/OperationUtils.h b/runtime/neurun/backend/srcn/kernel/OperationUtils.h index 4b6f12d..dce00b5 100644 --- a/runtime/neurun/backend/srcn/kernel/OperationUtils.h +++ b/runtime/neurun/backend/srcn/kernel/OperationUtils.h @@ -22,11 +22,11 @@ #include #include "model/Operand.h" -#include "model/DataType.h" +#include "ir/DataType.h" #include #include -using OperandType = neurun::model::DataType; +using OperandType = neurun::ir::DataType; using neurun::util::Coordinates; namespace neurun diff --git a/runtime/neurun/backend/srcn/operand/Tensor.h b/runtime/neurun/backend/srcn/operand/Tensor.h index 5cfb34d..af25593 100644 --- a/runtime/neurun/backend/srcn/operand/Tensor.h +++ b/runtime/neurun/backend/srcn/operand/Tensor.h @@ -43,7 +43,7 @@ public: public: void setBuffer(uint8_t *buffer) { _buffer = buffer; } - ::neurun::model::DataType data_type() const { return _info.typeInfo().type(); } + ir::DataType data_type() const { return _info.typeInfo().type(); } public: uint8_t *buffer() const override { return _buffer; } diff --git a/runtime/neurun/core/include/backend/CustomKernelBuilder.h b/runtime/neurun/core/include/backend/CustomKernelBuilder.h index b8fd906..848ebd5 100644 --- a/runtime/neurun/core/include/backend/CustomKernelBuilder.h +++ b/runtime/neurun/core/include/backend/CustomKernelBuilder.h @@ -20,7 +20,7 @@ #include "exec/IFunction.h" #include "misc/tensor/Shape.h" -#include "model/DataType.h" +#include "ir/DataType.h" #include #include @@ -37,7 +37,7 @@ using Shape = nnfw::misc::tensor::Shape; struct TypeInfo { Shape shape; - model::DataType dtype; + ir::DataType dtype; }; struct CustomKernelConfigParams diff --git a/runtime/neurun/core/include/backend/IConstantInitializer.h b/runtime/neurun/core/include/backend/IConstantInitializer.h index 0927d48..89535a4 100644 --- a/runtime/neurun/core/include/backend/IConstantInitializer.h +++ b/runtime/neurun/core/include/backend/IConstantInitializer.h @@ -215,7 +215,7 @@ protected: return; const auto type = obj.typeInfo().type(); - using neurun::model::DataType; + using ir::DataType; switch (type) { @@ -247,7 +247,7 @@ protected: return; const auto type = obj.typeInfo().type(); - using neurun::model::DataType; + using ir::DataType; using namespace std::placeholders; switch (type) diff --git a/runtime/neurun/core/include/model/DataType.h b/runtime/neurun/core/include/ir/DataType.h similarity index 84% rename from runtime/neurun/core/include/model/DataType.h rename to runtime/neurun/core/include/ir/DataType.h index 7b68dab..15f18a5 100644 --- a/runtime/neurun/core/include/model/DataType.h +++ b/runtime/neurun/core/include/ir/DataType.h @@ -14,14 +14,14 @@ * limitations under the License. */ -#ifndef __NEURUN_MODEL_DATATYPE_H__ -#define __NEURUN_MODEL_DATATYPE_H__ +#ifndef __NEURUN_IR_DATATYPE_H__ +#define __NEURUN_IR_DATATYPE_H__ #include namespace neurun { -namespace model +namespace ir { enum class DataType @@ -51,7 +51,13 @@ inline size_t sizeOfDataType(DataType data_type) } } +} // namespace ir + +// TODO Remove after merging 'model' and 'graph' namespaces. +namespace model +{ +using DataType = ir::DataType; } // namespace model } // namespace neurun -#endif // __NEURUN_MODEL_DATATYPE_H__ +#endif // __NEURUN_IR_DATATYPE_H__ diff --git a/runtime/neurun/core/include/model/Operand.h b/runtime/neurun/core/include/model/Operand.h index 470be4a..7d5832e 100644 --- a/runtime/neurun/core/include/model/Operand.h +++ b/runtime/neurun/core/include/model/Operand.h @@ -23,7 +23,7 @@ #include #include "Data.h" -#include "DataType.h" +#include "ir/DataType.h" #include "OperandInfo.h" #include "ir/operand/ParentInfo.h" // TODO Remove this dependency #include "model/OperationIndexList.h" @@ -55,7 +55,7 @@ public: void removeDef(const OperationIndex &idx); public: - void type(const DataType &type) { _info.type(type); }; + void type(const DataType type) { _info.type(type); }; public: void data(std::unique_ptr &&data) { _data = std::move(data); } diff --git a/runtime/neurun/core/include/model/OperandInfo.h b/runtime/neurun/core/include/model/OperandInfo.h index 7b0fdb0..66272c7 100644 --- a/runtime/neurun/core/include/model/OperandInfo.h +++ b/runtime/neurun/core/include/model/OperandInfo.h @@ -72,7 +72,7 @@ public: /** * @brief Set tensor data type */ - void type(const DataType &type) { _typeInfo.type(type); } + void type(const DataType type) { _typeInfo.type(type); } /** * @brief Return size of tensor (bytes) * @return Tensor size diff --git a/runtime/neurun/core/include/model/TypeInfo.h b/runtime/neurun/core/include/model/TypeInfo.h index 4d6a545..7b29085 100644 --- a/runtime/neurun/core/include/model/TypeInfo.h +++ b/runtime/neurun/core/include/model/TypeInfo.h @@ -19,7 +19,7 @@ #include -#include "DataType.h" +#include "ir/DataType.h" namespace neurun { @@ -42,7 +42,7 @@ public: int32_t offset() const { return _offset; } public: - void type(const DataType &type) { _type = type; } + void type(const DataType type) { _type = type; } private: DataType _type; diff --git a/runtime/neurun/core/include/model/operation/Permute.h b/runtime/neurun/core/include/model/operation/Permute.h index 51d6cb2..f7458ed 100644 --- a/runtime/neurun/core/include/model/operation/Permute.h +++ b/runtime/neurun/core/include/model/operation/Permute.h @@ -58,17 +58,17 @@ public: Permute(const OperandIndex &input, const OperandIndex &output, const backend::BackendContext *input_backend_ctx, const backend::BackendContext *output_backend_ctx, Type type, - model::DataType data_type = model::DataType::FLOAT32); + DataType data_type = DataType::FLOAT32); public: const Param ¶m() const { return _param; } - model::DataType getDataType() const { return _dataType; } + DataType getDataType() const { return _dataType; } Type getPermuteType() const { return _type; } private: Param _param; Type _type; - model::DataType _dataType; + DataType _dataType; }; } // namespace operation diff --git a/runtime/neurun/core/src/compiler/HEScheduler.cc b/runtime/neurun/core/src/compiler/HEScheduler.cc index 21241c7..8f623b5 100644 --- a/runtime/neurun/core/src/compiler/HEScheduler.cc +++ b/runtime/neurun/core/src/compiler/HEScheduler.cc @@ -53,7 +53,7 @@ static bool isQuant(const graph::Graph &graph, const model::Operation &node) for (const auto &input : node.getInputs()) { const auto &obj = graph.operands().at(input); - if (obj.typeInfo().type() == model::DataType::QUANT8_ASYMM) + if (obj.typeInfo().type() == ir::DataType::QUANT8_ASYMM) { return true; } @@ -408,7 +408,7 @@ int64_t HEScheduler::DFSChildrenMaxRank(const model::OperationIndex &index) for (const auto &output : node.getOutputs()) { const auto &operand = _graph->operands().at(output); - const bool quant = operand.typeInfo().type() == model::DataType::QUANT8_ASYMM; + const bool quant = operand.typeInfo().type() == ir::DataType::QUANT8_ASYMM; // average data transfer cost of this operand's data int64_t avg_transfer_cost = 1; for (const auto *backend : _all_backends) @@ -607,7 +607,7 @@ int64_t HEScheduler::predMaxEFT(const backend::Backend *backend, const model::Op for (const auto &input_operand_idx : node.getInputs()) { const auto &input_operand = _graph->operands().at(input_operand_idx); - const bool quant = input_operand.typeInfo().type() == model::DataType::QUANT8_ASYMM; + const bool quant = input_operand.typeInfo().type() == ir::DataType::QUANT8_ASYMM; for (const auto &input_node_idx : input_operand.getDef().list()) { diff --git a/runtime/neurun/core/src/compiler/OperationValidator.cc b/runtime/neurun/core/src/compiler/OperationValidator.cc index 8cdda66..3932be5 100644 --- a/runtime/neurun/core/src/compiler/OperationValidator.cc +++ b/runtime/neurun/core/src/compiler/OperationValidator.cc @@ -87,7 +87,7 @@ void OperationValidator::visit(const model::operation::Comparison &node) UNUSED_RELEASE(rhs_index); assert(_ctx.at(lhs_index).typeInfo().type() == _ctx.at(rhs_index).typeInfo().type()); - assert(_ctx.at(output_index).typeInfo().type() == model::DataType::BOOL8); + assert(_ctx.at(output_index).typeInfo().type() == ir::DataType::BOOL8); } void OperationValidator::visit(const model::operation::Softmax &node) @@ -377,7 +377,7 @@ void OperationValidator::visit(const model::operation::EmbeddingLookup &node) // Verify operand here, not at SimpleEmbeddingLookup::configure() to avoid acl's modifying // TensorShape sometimes(Issue: https://github.sec.samsung.net/STAR/nnfw/issues/729) { - assert(lookups_obj.typeInfo().type() == neurun::model::DataType::INT32); + assert(lookups_obj.typeInfo().type() == ir::DataType::INT32); const auto &output_shape = output_obj.shape(); const auto &lookups_shape = lookups_obj.shape(); @@ -441,9 +441,9 @@ void OperationValidator::visit(const model::operation::HashtableLookup &node) const auto &keys_obj = _ctx.at(keys_index); const auto &values_obj = _ctx.at(values_index); - assert(lookups_obj.typeInfo().type() == neurun::model::DataType::INT32); - assert(keys_obj.typeInfo().type() == neurun::model::DataType::INT32); - assert(hits_obj.typeInfo().type() == neurun::model::DataType::QUANT8_ASYMM); + assert(lookups_obj.typeInfo().type() == ir::DataType::INT32); + assert(keys_obj.typeInfo().type() == ir::DataType::INT32); + assert(hits_obj.typeInfo().type() == ir::DataType::QUANT8_ASYMM); const auto &output_shape = output_obj.shape(); const auto &hits_shape = hits_obj.shape(); @@ -533,8 +533,8 @@ void OperationValidator::visit(const model::operation::Dequantize &node) assert(_ctx.at(input_index).shape().rank() <= 4); assert(_ctx.at(input_index).shape() == _ctx.at(output_index).shape()); - assert(_ctx.at(input_index).typeInfo().type() == neurun::model::DataType::QUANT8_ASYMM); - assert(_ctx.at(output_index).typeInfo().type() == neurun::model::DataType::FLOAT32); + assert(_ctx.at(input_index).typeInfo().type() == ir::DataType::QUANT8_ASYMM); + assert(_ctx.at(output_index).typeInfo().type() == ir::DataType::FLOAT32); } void OperationValidator::visit(const model::operation::Mean &node) @@ -948,7 +948,7 @@ void OperationValidator::visit(const model::operation::Pad &node) assert(pad_shape.rank() == 2); assert(pad_shape.dim(0) == input_rank); assert(pad_shape.dim(1) == 2); - assert(_ctx.at(pad_index).typeInfo().type() == model::DataType::INT32); + assert(_ctx.at(pad_index).typeInfo().type() == ir::DataType::INT32); assert(_ctx.at(input_index).shape().rank() == _ctx.at(output_index).shape().rank()); } diff --git a/runtime/neurun/core/src/exec/ExecutionObservers.cc b/runtime/neurun/core/src/exec/ExecutionObservers.cc index 9d3b195..bc6a94b 100644 --- a/runtime/neurun/core/src/exec/ExecutionObservers.cc +++ b/runtime/neurun/core/src/exec/ExecutionObservers.cc @@ -52,7 +52,7 @@ void ProfileObserver::handleEnd(IExecutor *exec, const model::Subgraph *subgraph // fill ExecTime: bool is_quantized = exec->graph().operands().at(node->getInputs().at(0)).typeInfo().type() == - model::DataType::QUANT8_ASYMM; + ir::DataType::QUANT8_ASYMM; uint32_t size = 0; for (const auto &input : node->getInputs()) diff --git a/runtime/neurun/core/src/exec/ExecutorBase.cc b/runtime/neurun/core/src/exec/ExecutorBase.cc index 006c02f..ba316ed 100644 --- a/runtime/neurun/core/src/exec/ExecutorBase.cc +++ b/runtime/neurun/core/src/exec/ExecutorBase.cc @@ -34,7 +34,7 @@ std::unique_ptr ExecutorBase::source(const model::IOIndex &index, const model::TypeInfo &type, const void *buffer, size_t length, ir::Layout io_layout) { - using ::neurun::model::DataType; + using ir::DataType; switch (type.type()) { case DataType::FLOAT32: @@ -54,7 +54,7 @@ std::unique_ptr ExecutorBase::source(const model::IOIndex &index, std::unique_ptr ExecutorBase::sink(const model::IOIndex &index, const model::TypeInfo &type, void *buffer, size_t length, ir::Layout io_layout) { - using ::neurun::model::DataType; + using ir::DataType; switch (type.type()) { case DataType::FLOAT32: diff --git a/runtime/neurun/core/src/exec/interp/Tensor.h b/runtime/neurun/core/src/exec/interp/Tensor.h index 4617f7e..947ae5e 100644 --- a/runtime/neurun/core/src/exec/interp/Tensor.h +++ b/runtime/neurun/core/src/exec/interp/Tensor.h @@ -81,7 +81,7 @@ public: * @brief Return data type of tensor * @return Data type of tensor */ - virtual model::DataType data_type() const = 0; + virtual ir::DataType data_type() const = 0; /** * @brief Return TensorInfo * @return TensorInfo @@ -125,7 +125,7 @@ public: size_t calcOffset(const util::Coordinates &coords) const override; ir::Layout layout() const override; bool has_padding() const override { return false; } - model::DataType data_type() const override { return _info.typeInfo().type(); } + ir::DataType data_type() const override { return _info.typeInfo().type(); } const model::OperandInfo &tensorInfo() const override { return _info; } uint64_t num_elements() const override { return _info.shape().num_elements(); }; @@ -164,7 +164,7 @@ public: size_t calcOffset(const util::Coordinates &coords) const override; ir::Layout layout() const override; bool has_padding() const override { return false; } - model::DataType data_type() const override { return _info.typeInfo().type(); } + ir::DataType data_type() const override { return _info.typeInfo().type(); } const model::OperandInfo &tensorInfo() const override { return _info; } uint64_t num_elements() const override { return _info.shape().num_elements(); }; diff --git a/runtime/neurun/core/src/exec/interp/operations/Add.cc b/runtime/neurun/core/src/exec/interp/operations/Add.cc index 57fd2fd..c21a9a8 100644 --- a/runtime/neurun/core/src/exec/interp/operations/Add.cc +++ b/runtime/neurun/core/src/exec/interp/operations/Add.cc @@ -124,11 +124,11 @@ void invokeAdd(const ExecEnv *env, const model::Operation &node) const auto out_tensor = env->tensorAt(out_index); const auto data_type = lhs_tensor->data_type(); - if (data_type == model::DataType::INT32) + if (data_type == ir::DataType::INT32) { invoke(lhs_tensor, rhs_tensor, out_tensor, add_node.param()); } - else if (data_type == model::DataType::FLOAT32) + else if (data_type == ir::DataType::FLOAT32) { invoke(lhs_tensor, rhs_tensor, out_tensor, add_node.param()); } diff --git a/runtime/neurun/core/src/exec/interp/operations/AvgPool2D.cc b/runtime/neurun/core/src/exec/interp/operations/AvgPool2D.cc index 660514b..81ceaea 100644 --- a/runtime/neurun/core/src/exec/interp/operations/AvgPool2D.cc +++ b/runtime/neurun/core/src/exec/interp/operations/AvgPool2D.cc @@ -107,7 +107,7 @@ void invokeAvgPool2D(const ExecEnv *env, const model::Operation &node) const auto out_tensor = env->tensorAt(out_index); const auto data_type = in_tensor->data_type(); - if (data_type == model::DataType::FLOAT32) + if (data_type == ir::DataType::FLOAT32) { invoke(in_tensor, out_tensor, avgpool_node.param()); } diff --git a/runtime/neurun/core/src/exec/interp/operations/Concat.cc b/runtime/neurun/core/src/exec/interp/operations/Concat.cc index fcd1780..bcd90c5 100644 --- a/runtime/neurun/core/src/exec/interp/operations/Concat.cc +++ b/runtime/neurun/core/src/exec/interp/operations/Concat.cc @@ -130,7 +130,7 @@ void invokeConcat(const ExecEnv *env, const model::Operation &node) const uint32_t axis = (axis_raw < 0) ? (axis_raw + out_tensor->num_dimensions()) : axis_raw; const auto data_type = in_tensors[0]->data_type(); - if (data_type == model::DataType::FLOAT32) + if (data_type == ir::DataType::FLOAT32) { invoke(in_tensors, out_tensor, axis); } diff --git a/runtime/neurun/core/src/exec/interp/operations/Conv2D.cc b/runtime/neurun/core/src/exec/interp/operations/Conv2D.cc index d3b046f..cb2b97f 100644 --- a/runtime/neurun/core/src/exec/interp/operations/Conv2D.cc +++ b/runtime/neurun/core/src/exec/interp/operations/Conv2D.cc @@ -131,7 +131,7 @@ void invokeConv2D(const ExecEnv *env, const model::Operation &node) const auto ofm_tensor = env->tensorAt(ofm_index); const auto data_type = ifm_tensor->data_type(); - if (data_type == model::DataType::FLOAT32) + if (data_type == ir::DataType::FLOAT32) { invoke(ifm_tensor, ker_tensor, bias_tensor, ofm_tensor, conv_node.param()); } diff --git a/runtime/neurun/core/src/exec/interp/operations/DepthwiseConv.cc b/runtime/neurun/core/src/exec/interp/operations/DepthwiseConv.cc index 66dab69..c717f3d 100644 --- a/runtime/neurun/core/src/exec/interp/operations/DepthwiseConv.cc +++ b/runtime/neurun/core/src/exec/interp/operations/DepthwiseConv.cc @@ -136,7 +136,7 @@ void invokeDepthwiseConv(const ExecEnv *env, const model::Operation &node) const auto ofm_tensor = env->tensorAt(ofm_index); const auto data_type = ifm_tensor->data_type(); - if (data_type == model::DataType::FLOAT32) + if (data_type == ir::DataType::FLOAT32) { invoke(ifm_tensor, ker_tensor, bias_tensor, ofm_tensor, conv_node.param()); } diff --git a/runtime/neurun/core/src/exec/interp/operations/FullyConnected.cc b/runtime/neurun/core/src/exec/interp/operations/FullyConnected.cc index d03b0d0..0f1c0b9 100644 --- a/runtime/neurun/core/src/exec/interp/operations/FullyConnected.cc +++ b/runtime/neurun/core/src/exec/interp/operations/FullyConnected.cc @@ -115,7 +115,7 @@ void invokeFC(const ExecEnv *env, const model::Operation &node) const auto ofm_tensor = env->tensorAt(ofm_index); const auto data_type = ifm_tensor->data_type(); - if (data_type == model::DataType::FLOAT32) + if (data_type == ir::DataType::FLOAT32) { invoke(ifm_tensor, ker_tensor, bias_tensor, ofm_tensor, conv_node.param()); } diff --git a/runtime/neurun/core/src/exec/interp/operations/MaxPool2D.cc b/runtime/neurun/core/src/exec/interp/operations/MaxPool2D.cc index cd4e721..7d5256f 100644 --- a/runtime/neurun/core/src/exec/interp/operations/MaxPool2D.cc +++ b/runtime/neurun/core/src/exec/interp/operations/MaxPool2D.cc @@ -106,7 +106,7 @@ void invokeMaxPool2D(const ExecEnv *env, const model::Operation &node) const auto out_tensor = env->tensorAt(out_index); const auto data_type = in_tensor->data_type(); - if (data_type == model::DataType::FLOAT32) + if (data_type == ir::DataType::FLOAT32) { invoke(in_tensor, out_tensor, maxpool_node.param()); } diff --git a/runtime/neurun/core/src/exec/interp/operations/SoftMax.cc b/runtime/neurun/core/src/exec/interp/operations/SoftMax.cc index f7ddf02..5b1be21 100644 --- a/runtime/neurun/core/src/exec/interp/operations/SoftMax.cc +++ b/runtime/neurun/core/src/exec/interp/operations/SoftMax.cc @@ -141,7 +141,7 @@ void invokeSoftMax(const ExecEnv *env, const model::Operation &node) const auto in_data_type = in_tensor->data_type(); const auto out_data_type = out_tensor->data_type(); - if ((in_data_type == model::DataType::FLOAT32) && (out_data_type == model::DataType::FLOAT32)) + if ((in_data_type == ir::DataType::FLOAT32) && (out_data_type == ir::DataType::FLOAT32)) { invoke(in_tensor, out_tensor, softmax_node.param()); } diff --git a/runtime/neurun/core/src/model/operation/Permute.cc b/runtime/neurun/core/src/model/operation/Permute.cc index 91f771a..6c5f697 100644 --- a/runtime/neurun/core/src/model/operation/Permute.cc +++ b/runtime/neurun/core/src/model/operation/Permute.cc @@ -31,8 +31,7 @@ void Permute::accept(OperationVisitor &v) const { v.visit(*this); } Permute::Permute(const OperandIndex &input, const OperandIndex &output, const backend::BackendContext *input_backend_ctx, - const backend::BackendContext *output_backend_ctx, Type type, - model::DataType data_type) + const backend::BackendContext *output_backend_ctx, Type type, DataType data_type) : model::Operation{OperandConstraint::createExact(1u)}, _param{input_backend_ctx, output_backend_ctx}, _type{type}, _dataType{data_type} { diff --git a/runtime/neurun/frontend/base_loader/base_loader.h b/runtime/neurun/frontend/base_loader/base_loader.h index 2f28ac3..d95678a 100644 --- a/runtime/neurun/frontend/base_loader/base_loader.h +++ b/runtime/neurun/frontend/base_loader/base_loader.h @@ -66,7 +66,7 @@ protected: // Helper functions model::Activation convertActivation(ActivationFunctionType type); - model::DataType tensorTypeToDataType(TensorType type); + ir::DataType tensorTypeToDataType(TensorType type); // Create operands form tflite::Tensor model::OperandIndex loadOperand(const Tensor *tensor); @@ -174,19 +174,19 @@ model::Activation BaseLoader::BaseLoader::convertA } template -model::DataType +ir::DataType BaseLoader::BaseLoader::tensorTypeToDataType(const TensorType type) { switch (type) { case TensorType::TensorType_FLOAT32: - return model::DataType::FLOAT32; + return ir::DataType::FLOAT32; case TensorType::TensorType_INT32: - return model::DataType::INT32; + return ir::DataType::INT32; case TensorType::TensorType_BOOL: - return model::DataType::BOOL8; + return ir::DataType::BOOL8; case TensorType::TensorType_UINT8: - return model::DataType::QUANT8_ASYMM; + return ir::DataType::QUANT8_ASYMM; default: throw std::runtime_error( std::string("Unsupported tensor type: ").append(EnumNameTensorType(type))); @@ -204,7 +204,7 @@ model::OperandIndex BaseLoader::loadOperand(const shape.append(dim); } // Type - model::DataType data_type = tensorTypeToDataType(tensor->type()); + ir::DataType data_type = tensorTypeToDataType(tensor->type()); // Quantization auto q_params = tensor->quantization(); float scale = 0.0; @@ -279,7 +279,6 @@ void BaseLoader::loadStridesAndPaddings(Param &par const OptionsType *options) { model::Shape shape; - model::TypeInfo type_info(model::DataType::INT32); // Strides param.stride.vertical = options->stride_w(); param.stride.horizontal = options->stride_h(); @@ -300,7 +299,6 @@ void BaseLoader::loadPool2D(Param ¶m, loadStridesAndPaddings(param, options); // Filter width and height model::Shape shape; - model::TypeInfo type_info(model::DataType::INT32); // Strides param.kw = options->filter_width(); param.kh = options->filter_height(); @@ -339,7 +337,6 @@ void BaseLoader::loadDepthwiseConv2D(const Operato loadStridesAndPaddings(param, options); // Multiplier model::Shape shape; - model::TypeInfo type_info(model::DataType::INT32); param.multiplier = options->depth_multiplier(); // Dilation h/w factor unused std::unique_ptr new_op( @@ -441,7 +438,6 @@ void BaseLoader::loadConcatenation(const Operator const auto *options = op->builtin_options_as_ConcatenationOptions(); // Axis model::Shape shape; - model::TypeInfo type_info(model::DataType::INT32); param.axis = options->axis(); // activation unused diff --git a/runtime/neurun/frontend/nnapi/wrapper/NNAPIConvert.h b/runtime/neurun/frontend/nnapi/wrapper/NNAPIConvert.h index bd7fc6c..d736414 100644 --- a/runtime/neurun/frontend/nnapi/wrapper/NNAPIConvert.h +++ b/runtime/neurun/frontend/nnapi/wrapper/NNAPIConvert.h @@ -36,11 +36,8 @@ public: * @brief Convert data type from NNAPI to internal data type * @param[in] type NNAPI's data type * @return neurun's internal data type - * @note Now neurun::model::DataType shares the same enum value\n - with OperandCode in NeuralNetworks.h.\n - If we don't share same value, we must fix this mapping function. */ - static ::neurun::model::DataType getDataType(OperandCode type); + static neurun::ir::DataType getDataType(OperandCode type); /** * @brief Convert operand type info from NNAPI to interanl operand type info diff --git a/runtime/neurun/frontend/nnapi/wrapper/OperationFactory.cc b/runtime/neurun/frontend/nnapi/wrapper/OperationFactory.cc index b88629e..b3fef40 100644 --- a/runtime/neurun/frontend/nnapi/wrapper/OperationFactory.cc +++ b/runtime/neurun/frontend/nnapi/wrapper/OperationFactory.cc @@ -24,7 +24,7 @@ namespace { using namespace neurun::model; -void replaceDataType(Operands &operands, const OperandIndex &index, const DataType &type) +void replaceDataType(Operands &operands, const OperandIndex &index, const DataType type) { assert(operands.exist(index)); operands.at(index).type(type); diff --git a/runtime/neurun/test/core/compiler/Scheduler.cc b/runtime/neurun/test/core/compiler/Scheduler.cc index 04f6d71..66bfc3e 100644 --- a/runtime/neurun/test/core/compiler/Scheduler.cc +++ b/runtime/neurun/test/core/compiler/Scheduler.cc @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include diff --git a/runtime/neurun/test/core/exec/ExecInstance.cc b/runtime/neurun/test/core/exec/ExecInstance.cc index bd4a3c8..bbe8ba7 100644 --- a/runtime/neurun/test/core/exec/ExecInstance.cc +++ b/runtime/neurun/test/core/exec/ExecInstance.cc @@ -26,7 +26,7 @@ namespace { using namespace neurun::model; -using DataType = neurun::model::DataType; +using DataType = DataType; class CompiledMockUpModel { diff --git a/runtime/neurun/test/core/exec/interp/ExecManager.cc b/runtime/neurun/test/core/exec/interp/ExecManager.cc index 2915e78..2eba0ab 100644 --- a/runtime/neurun/test/core/exec/interp/ExecManager.cc +++ b/runtime/neurun/test/core/exec/interp/ExecManager.cc @@ -27,7 +27,7 @@ namespace { using namespace neurun::model; -using DataType = neurun::model::DataType; +using DataType = DataType; using ExecManager = neurun::exec::interp::ExecManager; using Execution = neurun::exec::Execution; diff --git a/runtime/neurun/test/graph/operand/Set.cc b/runtime/neurun/test/graph/operand/Set.cc index fce4223..44ede8c 100644 --- a/runtime/neurun/test/graph/operand/Set.cc +++ b/runtime/neurun/test/graph/operand/Set.cc @@ -30,7 +30,7 @@ TEST(graph_operand_Set, set_test) shape1.dim(2) = 30; shape1.dim(3) = 40; - ::neurun::model::TypeInfo type{neurun::model::DataType::INT32}; + ::neurun::model::TypeInfo type{neurun::ir::DataType::INT32}; set.emplace(shape0, type); set.emplace(shape1, type); diff --git a/runtime/neurun/test/graph/operand/UseDef.cc b/runtime/neurun/test/graph/operand/UseDef.cc index 1d7d64a..9e945ab 100644 --- a/runtime/neurun/test/graph/operand/UseDef.cc +++ b/runtime/neurun/test/graph/operand/UseDef.cc @@ -37,7 +37,7 @@ TEST(graph_operand_usedef, usedef_test) neurun::graph::verifier::DAGChecker verifier; neurun::model::Shape shape(3); - neurun::model::TypeInfo type{neurun::model::DataType::INT32}; + neurun::model::TypeInfo type{neurun::ir::DataType::INT32}; // Model Input/Output auto input_operand = graph.addOperand(shape, type); diff --git a/runtime/neurun/test/graph/operation/SetIO.cc b/runtime/neurun/test/graph/operation/SetIO.cc index 29309f9..ab0193f 100644 --- a/runtime/neurun/test/graph/operation/SetIO.cc +++ b/runtime/neurun/test/graph/operation/SetIO.cc @@ -34,7 +34,7 @@ TEST(graph_operation_setIO, operation_setIO_conv) neurun::graph::Graph graph; neurun::model::Shape shape{3}; - neurun::model::TypeInfo type{neurun::model::DataType::INT32}; + neurun::model::TypeInfo type{neurun::ir::DataType::INT32}; // Add Conv using Graph = neurun::model::operation::Conv2D; @@ -68,7 +68,7 @@ TEST(graph_operation_setIO, operation_setIO_concat) neurun::model::Shape shape{3}; - neurun::model::TypeInfo type{neurun::model::DataType::INT32}; + neurun::model::TypeInfo type{neurun::ir::DataType::INT32}; using Graph = neurun::model::operation::Concat; diff --git a/runtime/neurun/test/graph/verifier/Verifier.cc b/runtime/neurun/test/graph/verifier/Verifier.cc index d06c8ef..b430261 100644 --- a/runtime/neurun/test/graph/verifier/Verifier.cc +++ b/runtime/neurun/test/graph/verifier/Verifier.cc @@ -31,7 +31,7 @@ TEST(Verifier, dag_checker) neurun::graph::Graph graph; ::neurun::model::Shape shape{3}; - ::neurun::model::TypeInfo type{neurun::model::DataType::INT32}; + ::neurun::model::TypeInfo type{neurun::ir::DataType::INT32}; auto operand1 = graph.addOperand(shape, type); auto operand2 = graph.addOperand(shape, type); -- 2.7.4