From 398503ac97c9a38038c9a1b2420a47a516c0c875 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=D0=A1=D0=B5=D1=80=D0=B3=D0=B5=D0=B9=20=D0=91=D0=B0=D1=80?= =?utf8?q?=D0=B0=D0=BD=D0=BD=D0=B8=D0=BA=D0=BE=D0=B2/AI=20Tools=20Lab=20/S?= =?utf8?q?RR/Engineer/=EC=82=BC=EC=84=B1=EC=A0=84=EC=9E=90?= Date: Fri, 9 Aug 2019 15:12:11 +0300 Subject: [PATCH] [nnc] Reformat using .clang-format (#6455) Reformat sources to common style. Signed-off-by: Sergei Barannikov --- compiler/nnc/.FORMATDENY | 0 compiler/nnc/driver/Driver.cpp | 61 ++- compiler/nnc/driver/Driver.h | 15 +- compiler/nnc/driver/Options.cpp | 140 ++---- compiler/nnc/driver/main.cpp | 24 +- compiler/nnc/include/option/Options.h | 28 +- compiler/nnc/include/pass/Pass.h | 7 +- compiler/nnc/include/pass/PassData.h | 40 +- compiler/nnc/include/pass/PassException.h | 6 +- compiler/nnc/include/pass/PassManager.h | 8 +- .../passes/acl_soft_backend/AclCppException.h | 10 +- .../passes/acl_soft_backend/AclCppGenerator.h | 7 +- .../include/passes/common_frontend/NNImporter.h | 12 +- .../nnc/include/passes/dot_dumper/DumperPass.h | 11 +- .../nnc/include/passes/interpreter/Interpreter.h | 82 ++-- .../include/passes/interpreter/InterpreterPass.h | 9 +- .../passes/optimizations/CombineTransposes.h | 10 +- .../passes/optimizations/FuseArithmeticOps.h | 14 +- .../passes/optimizations/OptimizationUtils.h | 12 +- .../include/passes/optimizations/RemoveDeadEnds.h | 11 +- .../nnc/include/passes/optimizations/SinkRelu.h | 8 +- .../include/passes/optimizations/SinkTranspose.h | 8 +- .../include/passes/soft_backend/BaseGenerator.h | 14 +- .../nnc/include/passes/soft_backend/CGenerator.h | 5 +- .../nnc/include/passes/soft_backend/CPPGenerator.h | 53 +-- compiler/nnc/include/support/CommandLine.h | 248 +++++------ compiler/nnc/pass/PassManager.cpp | 8 +- .../passes/acl_soft_backend/AclCppGenerator.cpp | 11 +- .../passes/acl_soft_backend/AclCppOpGenerator.cpp | 468 ++++++++++++--------- .../passes/acl_soft_backend/AclCppOpGenerator.h | 169 ++++---- .../acl_soft_backend/ArtifactGeneratorCppCode.cpp | 130 +++--- .../acl_soft_backend/ArtifactGeneratorCppCode.h | 51 +-- .../acl_soft_backend/ArtifactGeneratorCppDecl.cpp | 79 ++-- .../acl_soft_backend/ArtifactGeneratorCppDecl.h | 49 +-- .../nnc/passes/acl_soft_backend/ArtifactIndent.h | 15 +- .../nnc/passes/acl_soft_backend/ArtifactModel.cpp | 66 +-- .../nnc/passes/acl_soft_backend/ArtifactModel.h | 453 ++++++++++---------- .../passes/acl_soft_backend/IArtifactGenerator.h | 43 +- compiler/nnc/passes/common_frontend/NNImporter.cpp | 31 +- compiler/nnc/passes/dot_dumper/DumperPass.cpp | 11 +- compiler/nnc/passes/interpreter/Interpreter.cpp | 133 +++--- .../nnc/passes/interpreter/interpreter_pass.cpp | 49 ++- compiler/nnc/passes/interpreter/ops/BatchNorm.h | 16 +- compiler/nnc/passes/interpreter/ops/Concat.h | 30 +- compiler/nnc/passes/interpreter/ops/Conv2D.cpp | 35 +- compiler/nnc/passes/interpreter/ops/Conv2D.h | 14 +- compiler/nnc/passes/interpreter/ops/DeConv2D.cpp | 47 ++- compiler/nnc/passes/interpreter/ops/DeConv2D.h | 14 +- .../nnc/passes/interpreter/ops/DepthwiseConv2D.cpp | 33 +- .../nnc/passes/interpreter/ops/DepthwiseConv2D.h | 13 +- compiler/nnc/passes/interpreter/ops/Dropout.h | 20 +- compiler/nnc/passes/interpreter/ops/Fill.h | 21 +- .../nnc/passes/interpreter/ops/FullyConnected.cpp | 29 +- .../nnc/passes/interpreter/ops/FullyConnected.h | 13 +- compiler/nnc/passes/interpreter/ops/Gather.cpp | 27 +- compiler/nnc/passes/interpreter/ops/Gather.h | 15 +- compiler/nnc/passes/interpreter/ops/Gemm.h | 42 +- .../nnc/passes/interpreter/ops/OperationImpl.h | 10 +- compiler/nnc/passes/interpreter/ops/Pad.cpp | 26 +- compiler/nnc/passes/interpreter/ops/Pad.h | 12 +- compiler/nnc/passes/interpreter/ops/Pool.cpp | 42 +- compiler/nnc/passes/interpreter/ops/Pool.h | 2 +- compiler/nnc/passes/interpreter/ops/Reduce.h | 43 +- compiler/nnc/passes/interpreter/ops/Reshape.h | 21 +- compiler/nnc/passes/interpreter/ops/Softmax.h | 22 +- compiler/nnc/passes/interpreter/ops/Transpose.cpp | 21 +- compiler/nnc/passes/interpreter/ops/Transpose.h | 12 +- compiler/nnc/passes/interpreter/ops/common.cpp | 6 +- compiler/nnc/passes/interpreter/ops/common.h | 7 +- .../nnc/passes/onnx_frontend/ONNXImporterPass.h | 2 +- .../nnc/passes/optimizations/CombineTransposes.cpp | 75 ++-- .../nnc/passes/optimizations/FuseArithmeticOps.cpp | 100 +++-- .../nnc/passes/optimizations/OptimizationUtils.cpp | 33 +- .../nnc/passes/optimizations/RemoveDeadEnds.cpp | 11 +- compiler/nnc/passes/optimizations/SinkRelu.cpp | 45 +- .../nnc/passes/optimizations/SinkTranspose.cpp | 50 ++- compiler/nnc/passes/soft_backend/BaseGenerator.cpp | 28 +- compiler/nnc/passes/soft_backend/CGenerator.cpp | 17 +- compiler/nnc/passes/soft_backend/CPPGenerator.cpp | 235 ++++++----- compiler/nnc/passes/soft_backend/ModelAnalyzer.cpp | 301 +++++++------ compiler/nnc/passes/soft_backend/ModelAnalyzer.h | 134 +++--- compiler/nnc/passes/soft_backend/SBSerializer.cpp | 144 ++++--- compiler/nnc/passes/soft_backend/SBSerializer.h | 101 +++-- compiler/nnc/passes/soft_backend/SequencedIR.h | 55 +-- compiler/nnc/support/CLOptionChecker.cpp | 27 +- compiler/nnc/support/CommandLine.cpp | 212 +++++----- .../tests/acl_soft_backend/AclCppOperations.cpp | 88 ++-- .../tests/acl_soft_backend/artifact_cmake/main.cpp | 59 ++- compiler/nnc/tests/import/caffe.cpp | 9 +- compiler/nnc/tests/soft_backend/CompileCPP.cpp | 31 +- compiler/nnc/unittests/acl_backend/DOMToText.cpp | 240 ++++++----- compiler/nnc/unittests/acl_backend/MIRToDOM.cpp | 226 +++++----- .../caffe2_frontend/test_data/gen_model.py | 2 +- .../caffe2_frontend/unsupported_caffe2_model.cpp | 9 +- .../caffe_frontend/unsupported_caffe_model.cpp | 10 +- .../unittests/optimizations/CombineTransposes.cpp | 65 +-- .../unittests/optimizations/FuseArithmeticOps.cpp | 10 +- .../nnc/unittests/optimizations/RemoveDeadEnds.cpp | 17 +- compiler/nnc/unittests/optimizations/SinkTest.cpp | 103 ++--- compiler/nnc/unittests/optimizations/Util.h | 30 +- compiler/nnc/unittests/pass/PassExceptionTest.cpp | 23 +- compiler/nnc/unittests/pass/PassManagerTest.cpp | 5 +- .../nnc/unittests/soft_backend/CPPHeaderTypes.cpp | 35 +- .../nnc/unittests/soft_backend/CPPOperations.cpp | 412 +++++++++--------- compiler/nnc/unittests/soft_backend/Generator.cpp | 43 +- .../nnc/unittests/soft_backend/ModelAnalyzer.cpp | 24 +- compiler/nnc/unittests/support/CommandLineTest.cpp | 188 +++------ .../tflite_frontend/test_data/gen_test.py | 18 +- .../tflite_frontend/unsupported_tflite_model.cpp | 9 +- .../nnc/utils/caffe2_dot_dumper/model_dump.cpp | 9 +- compiler/nnc/utils/caffe_dot_dumper/model_dump.cpp | 9 +- .../utils/caffe_model_maker/GenerateCaffeModels.py | 36 +- compiler/nnc/utils/caffe_model_maker/Pyloss.py | 1 + compiler/nnc/utils/def2src.cpp | 25 +- compiler/nnc/utils/infer_tests/infer_testcases.py | 58 +-- compiler/nnc/utils/infer_tests/res2bin.py | 43 +- compiler/nnc/utils/input_gen/tensor_gen.cpp | 89 ++-- compiler/nnc/utils/model_runner/common_place.py | 21 +- .../nnc/utils/model_runner/model_runner_caffe.py | 3 +- .../nnc/utils/model_runner/model_runner_caffe2.py | 5 +- .../nnc/utils/model_runner/model_runner_onnx.py | 4 +- .../nnc/utils/model_runner/model_runner_tflite.py | 2 + compiler/nnc/utils/prepare_inputs/jpeg2hdf5.py | 164 ++++---- .../nnc/utils/tflite_dot_dumper/sanity_check.cpp | 10 +- .../tflite_model_generator/ModelGenerator.cpp | 3 +- .../tflite_model_generator/RandomModelBuilder.h | 84 ++-- .../TFLiteRandomModelBuilder.cpp | 136 +++--- .../TFLiteRandomModelBuilder.h | 41 +- compiler/nnc/utils/tflite_model_generator/Tree.cpp | 129 ++++-- compiler/nnc/utils/tflite_model_generator/Tree.h | 45 +- 130 files changed, 3984 insertions(+), 3361 deletions(-) delete mode 100644 compiler/nnc/.FORMATDENY diff --git a/compiler/nnc/.FORMATDENY b/compiler/nnc/.FORMATDENY deleted file mode 100644 index e69de29..0000000 diff --git a/compiler/nnc/driver/Driver.cpp b/compiler/nnc/driver/Driver.cpp index 62125cb..117bb06 100644 --- a/compiler/nnc/driver/Driver.cpp +++ b/compiler/nnc/driver/Driver.cpp @@ -34,20 +34,24 @@ #include "option/Options.h" #include "Driver.h" -namespace nnc { +namespace nnc +{ /** * @brief run all registered passes * @throw PassException, if errors occured */ -void Driver::runPasses() { +void Driver::runPasses() +{ - const auto& registered_passes = _passManager.getPasses(); + const auto ®istered_passes = _passManager.getPasses(); PassData pass_data(nullptr); - for (auto &pass : registered_passes) { + for (auto &pass : registered_passes) + { pass_data = pass->run(pass_data); - if ( cli::dumpGraph && static_cast(pass_data)){ + if (cli::dumpGraph && static_cast(pass_data)) + { DumperPass d(pass->getName()); d.run(pass_data); } @@ -58,7 +62,8 @@ void Driver::runPasses() { } // runPasses -static std::string getFrontendOptionsString() { +static std::string getFrontendOptionsString() +{ std::string res; if (!cli::caffeFrontend.isDisabled()) @@ -80,20 +85,25 @@ static std::string getFrontendOptionsString() { * @brief Register frontend pass * @throw DriverException if errors occurred */ -void Driver::registerFrontendPass() { +void Driver::registerFrontendPass() +{ // For bool, the value false is converted to zero and the value true is converted to one if (cli::caffeFrontend + cli::caffe2Frontend + cli::tflFrontend + cli::onnxFrontend != 1) throw DriverException("One and only one of the following options are allowed and have to be set" - "in the same time: " + getFrontendOptionsString()); + "in the same time: " + + getFrontendOptionsString()); std::unique_ptr pass = NNImporter::createNNImporter(); - if (pass) { + if (pass) + { _passManager.registerPass(std::move(pass)); - } else { - throw DriverException("One of the following options must be defined: '" - + getFrontendOptionsString()); + } + else + { + throw DriverException("One of the following options must be defined: '" + + getFrontendOptionsString()); } } // registerFrontendPass @@ -102,17 +112,25 @@ void Driver::registerFrontendPass() { * @brief Register backend pass * @throw DriverException if errors occurred */ -void Driver::registerBackendPass() { +void Driver::registerBackendPass() +{ std::unique_ptr pass; - if (cli::target == NNC_TARGET_ARM_CPP || cli::target == NNC_TARGET_X86_CPP) { + if (cli::target == NNC_TARGET_ARM_CPP || cli::target == NNC_TARGET_X86_CPP) + { pass = std::unique_ptr(new CPPCodeGenerator()); - } else if (cli::target == NNC_TARGET_ARM_GPU_CPP) { + } + else if (cli::target == NNC_TARGET_ARM_GPU_CPP) + { pass = std::unique_ptr(new AclCppCodeGenerator()); - } else if (cli::target == NNC_TARGET_INTERPRETER) { + } + else if (cli::target == NNC_TARGET_INTERPRETER) + { pass = std::unique_ptr(new InterpreterPass()); - } else { + } + else + { assert(false && "invalid option value"); } @@ -120,8 +138,10 @@ void Driver::registerBackendPass() { } // registerBackendPass -void Driver::registerOptimizationPass() { - if (cli::doOptimizationPass) { +void Driver::registerOptimizationPass() +{ + if (cli::doOptimizationPass) + { // TODO: maybe we should start managing the optimizations more intelligently? _passManager.registerPass(std::unique_ptr(new CombineTransposes())); _passManager.registerPass(std::unique_ptr(new SinkTranspose())); @@ -134,7 +154,8 @@ void Driver::registerOptimizationPass() { } } // registerOptimizationPass -void Driver::runDriver() { +void Driver::runDriver() +{ // register passes registerFrontendPass(); diff --git a/compiler/nnc/driver/Driver.h b/compiler/nnc/driver/Driver.h index d3a5a94..9de06e7 100644 --- a/compiler/nnc/driver/Driver.h +++ b/compiler/nnc/driver/Driver.h @@ -22,18 +22,20 @@ #include "pass/PassManager.h" -namespace nnc { +namespace nnc +{ /** * @brief exceptions description class for compiler driver */ -class DriverException : public std::exception { +class DriverException : public std::exception +{ public: DriverException() = default; explicit DriverException(std::string reason) : _msg(std::move(reason)) {} - explicit DriverException(const char* msg) : _msg(msg) {} + explicit DriverException(const char *msg) : _msg(msg) {} - const char* what() const noexcept override { return _msg.c_str(); } + const char *what() const noexcept override { return _msg.c_str(); } private: std::string _msg; @@ -42,7 +44,8 @@ private: /** * @brief Compiler Driver manages the whole pipeline compilation process */ -class Driver { +class Driver +{ public: /** * @brief main method to run compiler driver @@ -62,4 +65,4 @@ private: } // namespace nnc -#endif //NNCC_DRIVER_H +#endif // NNCC_DRIVER_H diff --git a/compiler/nnc/driver/Options.cpp b/compiler/nnc/driver/Options.cpp index 0a1bb7c..dcf0a26 100644 --- a/compiler/nnc/driver/Options.cpp +++ b/compiler/nnc/driver/Options.cpp @@ -20,161 +20,109 @@ #include "option/Options.h" #include "Definitions.h" -namespace nnc { -namespace cli { +namespace nnc +{ +namespace cli +{ /** * Options for *compiler driver* */ -Option Help(optname("--help, -h"), - overview("print usage and exit"), - false, - optional(true)); -Option caffeFrontend(optname("--caffe"), - overview("treat input file as Caffe model"), - false, - optional(true), - optvalues(""), - nullptr, - separators(""), +Option Help(optname("--help, -h"), overview("print usage and exit"), false, optional(true)); +Option caffeFrontend(optname("--caffe"), overview("treat input file as Caffe model"), false, + optional(true), optvalues(""), nullptr, separators(""), #ifdef NNC_FRONTEND_CAFFE_ENABLED showopt(true) #else showopt(false) #endif // NNC_FRONTEND_CAFFE_ENABLED - ); -Option onnxFrontend(optname("--onnx"), - overview("treat input file as ONNX model"), - false, - optional(true), - optvalues(""), - nullptr, - separators(""), + ); +Option onnxFrontend(optname("--onnx"), overview("treat input file as ONNX model"), false, + optional(true), optvalues(""), nullptr, separators(""), #ifdef NNC_FRONTEND_ONNX_ENABLED - showopt(true) + showopt(true) #else - showopt(false) + showopt(false) #endif // NNC_FRONTEND_ONNX_ENABLED - ); + ); Option caffe2Frontend(optname("--caffe2"), - overview("treat input file as Caffe2 model (predict_net.pb)"), - false, - optional(false), - optvalues(""), - nullptr, - separators(""), + overview("treat input file as Caffe2 model (predict_net.pb)"), false, + optional(false), optvalues(""), nullptr, separators(""), #ifdef NNC_FRONTEND_CAFFE2_ENABLED showopt(true), #else showopt(false), #endif // NNC_FRONTEND_CAFFE2_ENABLED - IOption::Group::caffe2 - ); + IOption::Group::caffe2); -Option> inputShapes(optname("--input-shape"), - overview("Shape of caffe2 input"), - std::vector{}, - optional(false), - optvalues(""), - nullptr, +Option> inputShapes(optname("--input-shape"), overview("Shape of caffe2 input"), + std::vector{}, optional(false), optvalues(""), nullptr, separators(""), #ifdef NNC_FRONTEND_CAFFE2_ENABLED showopt(true), #else showopt(false), #endif // NNC_FRONTEND_CAFFE2_ENABLED - IOption::Group::caffe2 - ); + IOption::Group::caffe2); Option initNet(optname("--init-net"), - overview("path to Caffe2 model weights (init_net.pb)"), - std::string(), - optional(false), - optvalues(""), - checkInFile, - separators(""), + overview("path to Caffe2 model weights (init_net.pb)"), std::string(), + optional(false), optvalues(""), checkInFile, separators(""), #ifdef NNC_FRONTEND_CAFFE2_ENABLED showopt(true), #else showopt(false), #endif // NNC_FRONTEND_CAFFE2_ENABLED - IOption::Group::caffe2 - ); + IOption::Group::caffe2); Option tflFrontend(optname("--tflite"), - overview("treat input file as Tensor Flow Lite model"), - false, - optional(true), - optvalues(""), - nullptr, - separators(""), + overview("treat input file as Tensor Flow Lite model"), false, + optional(true), optvalues(""), nullptr, separators(""), #ifdef NNC_FRONTEND_TFLITE_ENABLED showopt(true) #else showopt(false) #endif // NNC_FRONTEND_TFLITE_ENABLED - ); -Option target(optname("--target"), - overview("select target language to emit for given architecture." - "Valid values are '" - NNC_TARGET_ARM_CPP "', '" - NNC_TARGET_X86_CPP "', '" - NNC_TARGET_ARM_GPU_CPP "', '" - NNC_TARGET_INTERPRETER "'"), - std::string(), - optional(false), - optvalues(NNC_TARGET_ARM_CPP "," - NNC_TARGET_X86_CPP "," - NNC_TARGET_ARM_GPU_CPP "," - NNC_TARGET_INTERPRETER), - nullptr, - separators("=")); + ); +Option + target(optname("--target"), + overview("select target language to emit for given architecture." + "Valid values are '" NNC_TARGET_ARM_CPP "', '" NNC_TARGET_X86_CPP + "', '" NNC_TARGET_ARM_GPU_CPP "', '" NNC_TARGET_INTERPRETER "'"), + std::string(), optional(false), + optvalues(NNC_TARGET_ARM_CPP "," NNC_TARGET_X86_CPP "," NNC_TARGET_ARM_GPU_CPP + "," NNC_TARGET_INTERPRETER), + nullptr, separators("=")); /** * Options for *frontend* */ Option inputFile(optname("--nnmodel, -m"), overview("specify input file with serialized NN models"), - std::string(), - optional(false), - optvalues(""), - checkInFile); + std::string(), optional(false), optvalues(""), checkInFile); /** * Options for *optimizer* */ -Option doOptimizationPass(optname("-O"), - overview("whether to optimize model or not"), - false, - optional(true), optvalues(""), nullptr, - separators(""), +Option doOptimizationPass(optname("-O"), overview("whether to optimize model or not"), false, + optional(true), optvalues(""), nullptr, separators(""), showopt(true)); Option dumpGraph(optname("--dump, -D"), - overview("dump graph to dot files after optimization passes"), - false, - optional(true), optvalues(""), nullptr, - separators(""), - showopt(true)); + overview("dump graph to dot files after optimization passes"), false, + optional(true), optvalues(""), nullptr, separators(""), showopt(true)); /** * Options for *backend* */ // options for soft backend -Option artifactName(optname("--output, -o"), - overview("specify name for output files"), - "nnmodel", - optional(true), - optvalues(""), - checkOutFile); +Option artifactName(optname("--output, -o"), overview("specify name for output files"), + "nnmodel", optional(true), optvalues(""), checkOutFile); Option artifactDir(optname("--output-dir, -d"), overview("specify directory for output files"), ".", // default is current directory - optional(true), - optvalues(""), - checkOutDir, - separators("=")); + optional(true), optvalues(""), checkOutDir, separators("=")); /** * Options for *interpreter* @@ -184,9 +132,7 @@ Option interInputDataDir(optname("--input-data-dir"), "containing the input data for the model " "(one file for each input with the same name)"), ".", // default is current directory - optional(true), - optvalues(""), - checkInDir); + optional(true), optvalues(""), checkInDir); } // namespace cli } // namespace nnc diff --git a/compiler/nnc/driver/main.cpp b/compiler/nnc/driver/main.cpp index 2b5c239..10d5edc 100644 --- a/compiler/nnc/driver/main.cpp +++ b/compiler/nnc/driver/main.cpp @@ -27,19 +27,25 @@ using namespace nnc; * Prints the explanatory string of an exception. If the exception is nested, recurses to print * the explanatory string of the exception it holds. */ -static void printException(const std::exception& e, int indent = 0) { +static void printException(const std::exception &e, int indent = 0) +{ std::cerr << std::string(indent, ' ') << e.what() << std::endl; - try { + try + { std::rethrow_if_nested(e); - } catch (const std::exception& e) { + } + catch (const std::exception &e) + { printException(e, indent + 2); } } -int main(int argc, const char* argv[]) { +int main(int argc, const char *argv[]) +{ int exit_code = EXIT_FAILURE; - try { + try + { // Parse command line cli::CommandLine::getParser()->parseCommandLine(argc, argv); @@ -54,10 +60,14 @@ int main(int argc, const char* argv[]) { // errors didn't happen exit_code = EXIT_SUCCESS; - } catch (const DriverException& e) { + } + catch (const DriverException &e) + { printException(e); std::cerr << "use --help for more information" << std::endl; - } catch (const PassException& e) { + } + catch (const PassException &e) + { printException(e); } diff --git a/compiler/nnc/include/option/Options.h b/compiler/nnc/include/option/Options.h index d49b17e..06994a4 100644 --- a/compiler/nnc/include/option/Options.h +++ b/compiler/nnc/include/option/Options.h @@ -32,37 +32,37 @@ extern Option caffe2Frontend; // frontend for CAFFE2 AI framework extern Option> inputShapes; extern Option initNet; -extern Option caffeFrontend; // frontend for CAFFE AI framework -extern Option tflFrontend; // frontend for TensorFlow Lite AI framework -extern Option onnxFrontend; // frontend for ONNX AI framework +extern Option caffeFrontend; // frontend for CAFFE AI framework +extern Option tflFrontend; // frontend for TensorFlow Lite AI framework +extern Option onnxFrontend; // frontend for ONNX AI framework extern Option doOptimizationPass; // enable optimization pass -extern Option dumpGraph; // enable Dumping graph to .dot files +extern Option dumpGraph; // enable Dumping graph to .dot files // valid values for target option -#define NNC_TARGET_ARM_CPP "arm-c++" -#define NNC_TARGET_X86_CPP "x86-c++" -#define NNC_TARGET_ARM_GPU_CPP "arm-gpu-c++" -#define NNC_TARGET_INTERPRETER "interpreter" -extern Option target; // kind of target for which compiler generates code +#define NNC_TARGET_ARM_CPP "arm-c++" +#define NNC_TARGET_X86_CPP "x86-c++" +#define NNC_TARGET_ARM_GPU_CPP "arm-gpu-c++" +#define NNC_TARGET_INTERPRETER "interpreter" +extern Option target; // kind of target for which compiler generates code /** * Frontend options */ -extern Option inputFile; // files contains model of specific AI framework +extern Option inputFile; // files contains model of specific AI framework /** * Options for backend */ -extern Option artifactDir; // output directory for artifact -extern Option artifactName; // name of artifact +extern Option artifactDir; // output directory for artifact +extern Option artifactName; // name of artifact /** * Options for interpreter */ -extern Option interInputDataDir; // directory with input data files +extern Option interInputDataDir; // directory with input data files } // namespace cli } // namespace nnc -#endif //NNCC_COMMANDLINEARGUMENTS_H +#endif // NNCC_COMMANDLINEARGUMENTS_H diff --git a/compiler/nnc/include/pass/Pass.h b/compiler/nnc/include/pass/Pass.h index b3bc574..d07d688 100644 --- a/compiler/nnc/include/pass/Pass.h +++ b/compiler/nnc/include/pass/Pass.h @@ -27,7 +27,8 @@ namespace nnc /** * @brief this class represent an interface for all compiler passes like that frontend, backend etc */ -class Pass { +class Pass +{ public: /** * @brief run compiler pass @@ -40,7 +41,7 @@ public: /** * @brief clean compiler pass data */ - virtual void cleanup() {}; + virtual void cleanup(){}; virtual ~Pass() = default; @@ -49,4 +50,4 @@ public: } // namespace nnc -#endif //NNCC_PASS_H +#endif // NNCC_PASS_H diff --git a/compiler/nnc/include/pass/PassData.h b/compiler/nnc/include/pass/PassData.h index 6de047e..e2c0b81 100644 --- a/compiler/nnc/include/pass/PassData.h +++ b/compiler/nnc/include/pass/PassData.h @@ -20,7 +20,6 @@ #include "mir/Graph.h" #include "mir/TensorVariant.h" - namespace nnc { @@ -30,20 +29,29 @@ namespace nnc class PassData { public: - /* implicit */ PassData(std::nullptr_t data) : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions) - _dataContainer{.unknown = data}, _dataType(PDT::UNKNOWN) {} + /* implicit */ PassData(std::nullptr_t data) + : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions) + _dataContainer{.unknown = data}, + _dataType(PDT::UNKNOWN) + { + } /** * @brief Implicit conversion from Graph* to PassData */ - /* implicit */ PassData(mir::Graph *graph) : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions) - _dataContainer{.graph = graph}, _dataType(PDT::GRAPH) {} + /* implicit */ PassData(mir::Graph *graph) + : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions) + _dataContainer{.graph = graph}, + _dataType(PDT::GRAPH) + { + } /** * @brief Implicit conversion from PassData to Graph* */ - /* implicit */ operator mir::Graph*() const { // NOLINT(google-explicit-constructor, hicpp-explicit-conversions) - if ( _dataType != PDT::GRAPH ) + /* implicit */ operator mir::Graph *() const + { // NOLINT(google-explicit-constructor, hicpp-explicit-conversions) + if (_dataType != PDT::GRAPH) return nullptr; return _dataContainer.graph; } @@ -51,14 +59,19 @@ public: /** * @brief Implicit conversion from Graph* to PassData */ - /* implicit */ PassData(mir::TensorVariant *tv) : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions) - _dataContainer{.tensorVariant = tv}, _dataType(PDT::TENSOR_VARIANT) {} + /* implicit */ PassData(mir::TensorVariant *tv) + : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions) + _dataContainer{.tensorVariant = tv}, + _dataType(PDT::TENSOR_VARIANT) + { + } /** * @brief Implicit conversion from PassData to Graph* */ - /* implicit */ operator mir::TensorVariant*() const { // NOLINT(google-explicit-constructor, hicpp-explicit-conversions) - if ( _dataType != PDT::TENSOR_VARIANT ) + /* implicit */ operator mir::TensorVariant *() const + { // NOLINT(google-explicit-constructor, hicpp-explicit-conversions) + if (_dataType != PDT::TENSOR_VARIANT) return nullptr; return _dataContainer.tensorVariant; } @@ -74,8 +87,7 @@ private: } _dataType; // union contains all pointers to objects that can be returned from passes - union - { + union { mir::Graph *graph; mir::TensorVariant *tensorVariant; void *unknown; @@ -85,4 +97,4 @@ private: } // namespace nnc -#endif //NNCC_PASSDATA_H +#endif // NNCC_PASSDATA_H diff --git a/compiler/nnc/include/pass/PassException.h b/compiler/nnc/include/pass/PassException.h index b82a5cb..d590fc7 100644 --- a/compiler/nnc/include/pass/PassException.h +++ b/compiler/nnc/include/pass/PassException.h @@ -31,9 +31,9 @@ class PassException : public std::exception public: PassException() = default; explicit PassException(std::string msg) : _msg(std::move(msg)) {} - explicit PassException(const char* msg) : _msg(msg) {} + explicit PassException(const char *msg) : _msg(msg) {} - const char* what() const noexcept override { return _msg.c_str(); } + const char *what() const noexcept override { return _msg.c_str(); } private: std::string _msg; @@ -41,4 +41,4 @@ private: } // namespace nnc -#endif //NNCC_PASSEXCEPTION_H +#endif // NNCC_PASSEXCEPTION_H diff --git a/compiler/nnc/include/pass/PassManager.h b/compiler/nnc/include/pass/PassManager.h index 09a5a73..3ce1c31 100644 --- a/compiler/nnc/include/pass/PassManager.h +++ b/compiler/nnc/include/pass/PassManager.h @@ -20,7 +20,8 @@ #include #include -namespace nnc { +namespace nnc +{ // forward declaration class Pass; @@ -28,7 +29,8 @@ class Pass; /** * @brief pass manager class. This class manages running of passes */ -class PassManager { +class PassManager +{ public: PassManager(); ~PassManager(); @@ -43,7 +45,7 @@ public: * @brief get all registered passes in order in which they were registered */ using Passes = std::vector>; - const Passes& getPasses() const { return _passes; } + const Passes &getPasses() const { return _passes; } private: // data diff --git a/compiler/nnc/include/passes/acl_soft_backend/AclCppException.h b/compiler/nnc/include/passes/acl_soft_backend/AclCppException.h index 66681c6..05193d3 100644 --- a/compiler/nnc/include/passes/acl_soft_backend/AclCppException.h +++ b/compiler/nnc/include/passes/acl_soft_backend/AclCppException.h @@ -19,17 +19,19 @@ #include "pass/PassException.h" -namespace nnc { +namespace nnc +{ /** * @brief objects of this class are to be thrown from ACL C++ soft backend if errors are occurred. */ -class AclCppException : public PassException { +class AclCppException : public PassException +{ public: - explicit AclCppException(const std::string& msg) : PassException(_prefix + msg) {} + explicit AclCppException(const std::string &msg) : PassException(_prefix + msg) {} private: - static constexpr const char* _prefix = "ACL C++ soft backend error: "; + static constexpr const char *_prefix = "ACL C++ soft backend error: "; }; } // namespace nnc diff --git a/compiler/nnc/include/passes/acl_soft_backend/AclCppGenerator.h b/compiler/nnc/include/passes/acl_soft_backend/AclCppGenerator.h index 7750c65..dd9372f 100644 --- a/compiler/nnc/include/passes/acl_soft_backend/AclCppGenerator.h +++ b/compiler/nnc/include/passes/acl_soft_backend/AclCppGenerator.h @@ -19,14 +19,15 @@ #include "pass/Pass.h" - -namespace nnc { +namespace nnc +{ /** * @brief Class for the ACL C++ code generator. * It is the entry point to the ACL C++ soft backend. */ -class AclCppCodeGenerator: public Pass { +class AclCppCodeGenerator : public Pass +{ public: /** * @brief Method represents the generation sequence: analysis, serialization, diff --git a/compiler/nnc/include/passes/common_frontend/NNImporter.h b/compiler/nnc/include/passes/common_frontend/NNImporter.h index 33526f4..5fe74fd 100644 --- a/compiler/nnc/include/passes/common_frontend/NNImporter.h +++ b/compiler/nnc/include/passes/common_frontend/NNImporter.h @@ -20,17 +20,17 @@ #include "pass/Pass.h" #include "mir/Graph.h" -namespace nnc { +namespace nnc +{ /** * @brief Interface for all frontends. All who uses frontends must do it thought this interface */ -class NNImporter : public Pass { +class NNImporter : public Pass +{ public: // template method pattern - PassData run(PassData /*data*/) final { - return importModel(); - } + PassData run(PassData /*data*/) final { return importModel(); } static std::unique_ptr createNNImporter(); @@ -38,7 +38,7 @@ public: virtual mir::Graph *importModel() = 0; - std::string getName() override { return "importer";}; + std::string getName() override { return "importer"; }; }; } // namespace nnc diff --git a/compiler/nnc/include/passes/dot_dumper/DumperPass.h b/compiler/nnc/include/passes/dot_dumper/DumperPass.h index b5d77e7..9998d87 100644 --- a/compiler/nnc/include/passes/dot_dumper/DumperPass.h +++ b/compiler/nnc/include/passes/dot_dumper/DumperPass.h @@ -21,21 +21,24 @@ #include "pass/PassData.h" #include "mir/IrDotDumper.h" -namespace nnc { +namespace nnc +{ /** * @brief Dumps the graph to a dot file named %number%.dot * where %number% is how many times the graph was dumped. */ -class DumperPass : public Pass { +class DumperPass : public Pass +{ public: - explicit DumperPass(std::string s): _file_name(std::move(s)){}; + explicit DumperPass(std::string s) : _file_name(std::move(s)){}; PassData run(PassData data) override; + private: std::string _file_name; static int _counter; }; } // namespace nnc -#endif //NNCC_DUMPERPASS_H +#endif // NNCC_DUMPERPASS_H diff --git a/compiler/nnc/include/passes/interpreter/Interpreter.h b/compiler/nnc/include/passes/interpreter/Interpreter.h index 15d0761..51c1ec8 100644 --- a/compiler/nnc/include/passes/interpreter/Interpreter.h +++ b/compiler/nnc/include/passes/interpreter/Interpreter.h @@ -24,65 +24,67 @@ #include #include -namespace nnc { +namespace nnc +{ -class NNInterpreter : public mir::IVisitor { +class NNInterpreter : public mir::IVisitor +{ public: explicit NNInterpreter() = default; ~NNInterpreter() override = default; - void setInput(const std::string& name, const mir::TensorVariant& data); + void setInput(const std::string &name, const mir::TensorVariant &data); - mir::TensorVariant getResult(const mir::Operation::Output* tensor); + mir::TensorVariant getResult(const mir::Operation::Output *tensor); - void visit(mir::ops::AddOp& op) override; - void visit(mir::ops::BatchNormOp& op) override; - void visit(mir::ops::CappedReluOp& op) override; - void visit(mir::ops::ConcatOp& op) override; - void visit(mir::ops::ConstantOp& op) override; - void visit(mir::ops::Conv2DOp& op) override; - void visit(mir::ops::DeConv2DOp& op) override; - void visit(mir::ops::DepthwiseConv2DOp& op) override; - void visit(mir::ops::DivOp& op) override; - void visit(mir::ops::DropoutOp& op) override; - void visit(mir::ops::EluOp& op) override; - void visit(mir::ops::FullyConnectedOp& op) override; - void visit(mir::ops::GatherOp& op) override; - void visit(mir::ops::GemmOp& op) override; - void visit(mir::ops::InputOp& op) override; - void visit(mir::ops::LeakyReluOp& op) override; - void visit(mir::ops::MaxOp& op) override; - void visit(mir::ops::MulOp& op) override; - void visit(mir::ops::OutputOp& op) override; - void visit(mir::ops::PadOp& op) override; - void visit(mir::ops::PoolOp& op) override; - void visit(mir::ops::ReduceOp& op) override; - void visit(mir::ops::ReluOp& op) override; - void visit(mir::ops::ReshapeOp& op) override; - void visit(mir::ops::ResizeOp& op) override; - void visit(mir::ops::SigmoidOp& op) override; - void visit(mir::ops::SliceOp& op) override; - void visit(mir::ops::SoftmaxOp& op) override; - void visit(mir::ops::SqrtOp& op) override; - void visit(mir::ops::SqueezeOp& op) override; - void visit(mir::ops::SubOp& op) override; - void visit(mir::ops::TanhOp& op) override; - void visit(mir::ops::TransposeOp& op) override; + void visit(mir::ops::AddOp &op) override; + void visit(mir::ops::BatchNormOp &op) override; + void visit(mir::ops::CappedReluOp &op) override; + void visit(mir::ops::ConcatOp &op) override; + void visit(mir::ops::ConstantOp &op) override; + void visit(mir::ops::Conv2DOp &op) override; + void visit(mir::ops::DeConv2DOp &op) override; + void visit(mir::ops::DepthwiseConv2DOp &op) override; + void visit(mir::ops::DivOp &op) override; + void visit(mir::ops::DropoutOp &op) override; + void visit(mir::ops::EluOp &op) override; + void visit(mir::ops::FullyConnectedOp &op) override; + void visit(mir::ops::GatherOp &op) override; + void visit(mir::ops::GemmOp &op) override; + void visit(mir::ops::InputOp &op) override; + void visit(mir::ops::LeakyReluOp &op) override; + void visit(mir::ops::MaxOp &op) override; + void visit(mir::ops::MulOp &op) override; + void visit(mir::ops::OutputOp &op) override; + void visit(mir::ops::PadOp &op) override; + void visit(mir::ops::PoolOp &op) override; + void visit(mir::ops::ReduceOp &op) override; + void visit(mir::ops::ReluOp &op) override; + void visit(mir::ops::ReshapeOp &op) override; + void visit(mir::ops::ResizeOp &op) override; + void visit(mir::ops::SigmoidOp &op) override; + void visit(mir::ops::SliceOp &op) override; + void visit(mir::ops::SoftmaxOp &op) override; + void visit(mir::ops::SqrtOp &op) override; + void visit(mir::ops::SqueezeOp &op) override; + void visit(mir::ops::SubOp &op) override; + void visit(mir::ops::TanhOp &op) override; + void visit(mir::ops::TransposeOp &op) override; private: /// @brief Gets the computed inputs for the operation. std::vector> - getInputTensors(const mir::Operation& op); + getInputTensors(const mir::Operation &op); /// @brief Saves the computed outputs for the operation. - void setOutputTensors(const mir::Operation& op, std::vector&& outputs); + void setOutputTensors(const mir::Operation &op, std::vector &&outputs); /// @brief Mapping of graph named inputs to their values. std::unordered_map _inputTensors; /// @brief Mapping of operations to their computed results. - std::unordered_map> _opResults; + std::unordered_map> _opResults; }; } // namespace nnc diff --git a/compiler/nnc/include/passes/interpreter/InterpreterPass.h b/compiler/nnc/include/passes/interpreter/InterpreterPass.h index a521d12..90f3510 100644 --- a/compiler/nnc/include/passes/interpreter/InterpreterPass.h +++ b/compiler/nnc/include/passes/interpreter/InterpreterPass.h @@ -24,10 +24,11 @@ #include "pass/Pass.h" #include "pass/PassData.h" +namespace nnc +{ -namespace nnc { - -class InterpreterPass : public Pass { +class InterpreterPass : public Pass +{ public: ~InterpreterPass() override; @@ -36,4 +37,4 @@ public: } // namespace nnc -#endif //NNCC_INTERPRETERPASS_H +#endif // NNCC_INTERPRETERPASS_H diff --git a/compiler/nnc/include/passes/optimizations/CombineTransposes.h b/compiler/nnc/include/passes/optimizations/CombineTransposes.h index 963c641..7d227cd 100644 --- a/compiler/nnc/include/passes/optimizations/CombineTransposes.h +++ b/compiler/nnc/include/passes/optimizations/CombineTransposes.h @@ -20,20 +20,22 @@ #include "pass/Pass.h" #include "pass/PassData.h" -namespace nnc { +namespace nnc +{ /** * @brief This pass combines sequential transposes and removes identity transposes if * the combination results in an identity permutation. */ -class CombineTransposes : public Pass { +class CombineTransposes : public Pass +{ public: PassData run(PassData data) override; - std::string getName() override {return "opt_combine_transposes";}; + std::string getName() override { return "opt_combine_transposes"; }; private: }; } // namespace nnc -#endif //NNCC_COMBINE_TRANSPOSES_H +#endif // NNCC_COMBINE_TRANSPOSES_H diff --git a/compiler/nnc/include/passes/optimizations/FuseArithmeticOps.h b/compiler/nnc/include/passes/optimizations/FuseArithmeticOps.h index 8259a18..ae39e4c 100644 --- a/compiler/nnc/include/passes/optimizations/FuseArithmeticOps.h +++ b/compiler/nnc/include/passes/optimizations/FuseArithmeticOps.h @@ -20,23 +20,25 @@ #include "pass/Pass.h" #include "pass/PassData.h" -namespace nnc { +namespace nnc +{ /** * @brief Main purpose of this pass - is to fuse 'Conv->BatchNorm' into 'Conv' * Currently 'BatchNorm' split by NNC frontends into 'Scale->Scale->BiasAdd' * This optimization performs in two steps (repeated while graph changing): - * 1. Fuse two successive operations with constant weights into one (ex: 'Scale->Scale' becomes 'Scale') + * 1. Fuse two successive operations with constant weights into one (ex: 'Scale->Scale' becomes + * 'Scale') * 2. Sink 'BiasAdd' through 'Scale' (so 'Conv->BiasAdd->Scale' becomes 'Conv->Scale->BiasAdd') */ -class FuseArithmeticOps : public Pass { +class FuseArithmeticOps : public Pass +{ public: PassData run(PassData data) override; std::string getName() override { return "FuseArithmeticOps"; } }; -} // namespace nnc +} // namespace nnc - -#endif // NNCC_FUSE_ARITHMETIC_OPS_H +#endif // NNCC_FUSE_ARITHMETIC_OPS_H diff --git a/compiler/nnc/include/passes/optimizations/OptimizationUtils.h b/compiler/nnc/include/passes/optimizations/OptimizationUtils.h index bec4c80..9a9212c 100644 --- a/compiler/nnc/include/passes/optimizations/OptimizationUtils.h +++ b/compiler/nnc/include/passes/optimizations/OptimizationUtils.h @@ -20,19 +20,21 @@ #include "mir/Operation.h" #include "mir/Graph.h" -namespace nnc { -namespace opt_util { +namespace nnc +{ +namespace opt_util +{ /** * @brief Swap adjacent nodes in Graph. Creates new nodes and replaces the old ones with new. * @param g MIR Graph * @param top Node * @param bottom Node */ - void swapAdjacent(mir::Graph* g, mir::Operation* top, mir::Operation* bottom); +void swapAdjacent(mir::Graph *g, mir::Operation *top, mir::Operation *bottom); // TODO: this function and it's usages should be removed, after DCE optimization will be implemented - void removeNodeIfUnused(mir::Graph* g, mir::Operation* op); +void removeNodeIfUnused(mir::Graph *g, mir::Operation *op); } // namespace opt_util } // namespace nnc -#endif //NNCC_OPTIMIZATION_UTILS_H +#endif // NNCC_OPTIMIZATION_UTILS_H diff --git a/compiler/nnc/include/passes/optimizations/RemoveDeadEnds.h b/compiler/nnc/include/passes/optimizations/RemoveDeadEnds.h index 16dc41a..6225f6a 100644 --- a/compiler/nnc/include/passes/optimizations/RemoveDeadEnds.h +++ b/compiler/nnc/include/passes/optimizations/RemoveDeadEnds.h @@ -20,20 +20,21 @@ #include "pass/Pass.h" #include "pass/PassData.h" -namespace nnc { +namespace nnc +{ /** * @brief This pass removes operations without uses. * Importers currently only generate `sConstantOp`s without uses. */ -class RemoveDeadEnds : public Pass { +class RemoveDeadEnds : public Pass +{ public: PassData run(PassData data) override; - std::string getName() override {return "RemoveDeadEnds";}; + std::string getName() override { return "RemoveDeadEnds"; }; }; } // namespace nnc - -#endif //NNCC_REMOVEDEADENDS_H +#endif // NNCC_REMOVEDEADENDS_H diff --git a/compiler/nnc/include/passes/optimizations/SinkRelu.h b/compiler/nnc/include/passes/optimizations/SinkRelu.h index 8a27853..edb1814 100644 --- a/compiler/nnc/include/passes/optimizations/SinkRelu.h +++ b/compiler/nnc/include/passes/optimizations/SinkRelu.h @@ -20,12 +20,14 @@ #include "pass/Pass.h" #include "pass/PassData.h" -namespace nnc { +namespace nnc +{ /** * @brief This pass sinks relu below MaxPooling and Concat nodes. */ -class SinkRelu : public Pass { +class SinkRelu : public Pass +{ public: PassData run(PassData data) override; @@ -34,4 +36,4 @@ public: } // namespace nnc -#endif //NNCC_SINKRELU_H +#endif // NNCC_SINKRELU_H diff --git a/compiler/nnc/include/passes/optimizations/SinkTranspose.h b/compiler/nnc/include/passes/optimizations/SinkTranspose.h index 2515b10..04e5c99 100644 --- a/compiler/nnc/include/passes/optimizations/SinkTranspose.h +++ b/compiler/nnc/include/passes/optimizations/SinkTranspose.h @@ -20,13 +20,15 @@ #include "pass/Pass.h" #include "pass/PassData.h" -namespace nnc { +namespace nnc +{ /** * @brief This pass sinks transposes below Relu and Concat nodes (in that order). * `concat(relu(tr(x)), relu(tr(y))) -> tr(concat'(relu(x), relu(y)))` */ -class SinkTranspose : public Pass { +class SinkTranspose : public Pass +{ public: PassData run(PassData data) override; @@ -35,4 +37,4 @@ public: } // namespace nnc -#endif //NNCC_SINKTRANSPOSE_H +#endif // NNCC_SINKTRANSPOSE_H diff --git a/compiler/nnc/include/passes/soft_backend/BaseGenerator.h b/compiler/nnc/include/passes/soft_backend/BaseGenerator.h index dde9e16..409e8ba 100644 --- a/compiler/nnc/include/passes/soft_backend/BaseGenerator.h +++ b/compiler/nnc/include/passes/soft_backend/BaseGenerator.h @@ -24,8 +24,8 @@ #include #include - -namespace nnc { +namespace nnc +{ class ModelAnalyzer; @@ -40,14 +40,17 @@ class Serializer; * + code file generation function: materuializeCode * + header file generation to expose artifact inerface to user */ -class BaseCodeGenerator : public Pass { +class BaseCodeGenerator : public Pass +{ public: /** - * @brief Method represents base generation sequence: analysis, serialization, header/code generation, etc + * @brief Method represents base generation sequence: analysis, serialization, header/code + * generation, etc * @param data PassData object containing Model IR * @return returns empty PassData object */ PassData run(PassData data) override; + protected: /** * @brief This function processes tensor names @@ -65,7 +68,8 @@ protected: * @brief Derivative classes should override this function to generate implementation of artifact * @param out Stream to write header text * @param ma Intermediate artifact information - * @param s Serializer holds parameters of network and various meta-information: serializer version, hashes, etc + * @param s Serializer holds parameters of network and various meta-information: serializer + * version, hashes, etc */ virtual void materializeCode(std::ostream &out, const ModelAnalyzer &ma, const Serializer &s) = 0; /** diff --git a/compiler/nnc/include/passes/soft_backend/CGenerator.h b/compiler/nnc/include/passes/soft_backend/CGenerator.h index e0e984d..92b78cd 100644 --- a/compiler/nnc/include/passes/soft_backend/CGenerator.h +++ b/compiler/nnc/include/passes/soft_backend/CGenerator.h @@ -25,9 +25,10 @@ namespace nnc /** * @brief CCodeGenerator implements interfaces that provides BaseCodeGenerator for C language - * This includes header file generation, code file generation and variable renaming according to C naming requirements + * This includes header file generation, code file generation and variable renaming according to C + * naming requirements */ -class CCodeGenerator: public BaseCodeGenerator +class CCodeGenerator : public BaseCodeGenerator { public: static Pass &getInstance(); diff --git a/compiler/nnc/include/passes/soft_backend/CPPGenerator.h b/compiler/nnc/include/passes/soft_backend/CPPGenerator.h index 5f21432..8c1d8c0 100644 --- a/compiler/nnc/include/passes/soft_backend/CPPGenerator.h +++ b/compiler/nnc/include/passes/soft_backend/CPPGenerator.h @@ -20,26 +20,29 @@ #include "passes/soft_backend/BaseGenerator.h" #include "pass/Pass.h" -namespace nnc { +namespace nnc +{ -namespace sir { +namespace sir +{ struct TensorDescriptor; struct Action; struct CallFunction; struct TransposeTensor; struct CreateTmp; struct DestroyTmp; -} // namespace sir - +} // namespace sir /** * @brief CPPCodeGenerator implements interfaces that provides BaseCodeGenerator for C++ language - * This includes header file generation, code file generation and variable renaming according to C++ naming requirements + * This includes header file generation, code file generation and variable renaming according to C++ + * naming requirements */ -class CPPCodeGenerator: public BaseCodeGenerator { +class CPPCodeGenerator : public BaseCodeGenerator +{ protected: - void formatTensorNames(const ModelAnalyzer& ma) override; - void materializeHeader(std::ostream& out, const ModelAnalyzer& ma) override; + void formatTensorNames(const ModelAnalyzer &ma) override; + void materializeHeader(std::ostream &out, const ModelAnalyzer &ma) override; /** * @brief Form list of function call arguments @@ -47,9 +50,8 @@ protected: * @param argIds List of argument variable ids * @param args Result list of arguments transformed in form of strings */ - void gatherOperationArguments(const ModelAnalyzer& ma, - const std::vector& arg_ids, - std::vector& args); + void gatherOperationArguments(const ModelAnalyzer &ma, const std::vector &arg_ids, + std::vector &args); /** * @brief Prints setter of artifact * @param out Output stream @@ -57,8 +59,8 @@ protected: * @param setterName Name of setter function * @param varId id of variable that setter fills */ - void printSetter(std::ostream& out, const std::string& class_name, - const std::string& setter_name, const sir::TensorDescriptor& td); + void printSetter(std::ostream &out, const std::string &class_name, const std::string &setter_name, + const sir::TensorDescriptor &td); /** * @brief Prints getters of artifact * @param out Output stream @@ -66,48 +68,47 @@ protected: * @param setterName Name of setter function * @param varId id of variable that getter returns */ - void printGetter(std::ostream& out, const std::string& class_name, - const std::string& getter_name, const sir::TensorDescriptor& td); + void printGetter(std::ostream &out, const std::string &class_name, const std::string &getter_name, + const sir::TensorDescriptor &td); /** * @brief Generate code for function call action * @param out Output stream to print * @param ma Intermediate model representation * @param call Action to generate code from */ - void materializeCall(std::ostream& out, const ModelAnalyzer& ma, - const nnc::sir::CallFunction* call); + void materializeCall(std::ostream &out, const ModelAnalyzer &ma, + const nnc::sir::CallFunction *call); /** * @brief Generate code for transpose action * @param out Output stream to print * @param ma Intermediate model representation * @param action Action to generate code from */ - void materializeTranspose(std::ostream& out, const ModelAnalyzer& ma, - const nnc::sir::TransposeTensor* transpose); + void materializeTranspose(std::ostream &out, const ModelAnalyzer &ma, + const nnc::sir::TransposeTensor *transpose); /** * @brief Generate code for constructor action * @param out Output stream to print * @param ma Intermediate model representation * @param action Action to generate code from */ - void materializeConstructor(std::ostream& out, const ModelAnalyzer& ma, - const nnc::sir::CreateTmp* constructor); + void materializeConstructor(std::ostream &out, const ModelAnalyzer &ma, + const nnc::sir::CreateTmp *constructor); /** * @brief Generate code for destructor action * @param out Output stream to print * @param ma Intermediate model representation * @param action Action to generate code from */ - void materializeDestructor(std::ostream& out, const ModelAnalyzer& ma, - const nnc::sir::DestroyTmp* destructor); + void materializeDestructor(std::ostream &out, const ModelAnalyzer &ma, + const nnc::sir::DestroyTmp *destructor); /** * @brief Prints inference sequence placed in doInference method of artifact * @param out Output stream * @param ma Intermediate model representation */ - void materializeInferenceSequence(std::ostream& out, const ModelAnalyzer& ma); - void materializeCode(std::ostream& out, const ModelAnalyzer& ma, const Serializer& s) override; - + void materializeInferenceSequence(std::ostream &out, const ModelAnalyzer &ma); + void materializeCode(std::ostream &out, const ModelAnalyzer &ma, const Serializer &s) override; }; } // namespace nnc diff --git a/compiler/nnc/include/support/CommandLine.h b/compiler/nnc/include/support/CommandLine.h index 6eb84f4..40777ff 100644 --- a/compiler/nnc/include/support/CommandLine.h +++ b/compiler/nnc/include/support/CommandLine.h @@ -26,27 +26,31 @@ #include #include -namespace nnc { -namespace cli { +namespace nnc +{ +namespace cli +{ /** * @brief simple exception class for invalid options */ -class BadOption : public std::logic_error { +class BadOption : public std::logic_error +{ public: - explicit BadOption(const std::string& msg, std::string optname = "", std::string value = "") - : std::logic_error(msg), _option_name(std::move(optname)), - _option_value(std::move(value)) {} + explicit BadOption(const std::string &msg, std::string optname = "", std::string value = "") + : std::logic_error(msg), _option_name(std::move(optname)), _option_value(std::move(value)) + { + } /** * @brief get name for invalid option */ - const std::string& getName() const { return _option_name; } + const std::string &getName() const { return _option_name; } /** * @brief get value for invalid option */ - const std::string& getValue() const { return _option_value; } + const std::string &getValue() const { return _option_value; } private: std::string _option_name; @@ -56,63 +60,64 @@ private: /** * @brief a class models option type */ -template -class OptionType { +template class OptionType +{ public: OptionType() = default; }; // for class type -template -class OptionType : public T { +template class OptionType : public T +{ public: /** * @brief set value for option * @tparam Tval - type of value what we want to assign to value * @param val - option value */ - template - void setRawValue(const Tval& val) { this->T::operator=(val); } + template void setRawValue(const Tval &val) { this->T::operator=(val); } /** * @brief get option value * @return value of option */ - const T& getRawValue() const { return *this; } + const T &getRawValue() const { return *this; } T getRawValue() { return *this; } }; // for scalar type -template -class OptionType { +template class OptionType +{ public: /** * @brief convert Option to scalar option type */ - /*implicit*/ operator T() const { return _value; } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) + /*implicit*/ operator T() const + { + return _value; + } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) /** * @brief set value for option * @tparam Tval - type of value what we want to assign to value * @param val - option value */ - template - void setRawValue(const Tval& val) { _value = val; } + template void setRawValue(const Tval &val) { _value = val; } /** * @brief get option value * @return value of option */ - const T& getRawValue() const { return _value; } + const T &getRawValue() const { return _value; } T getRawValue() { return _value; } protected: // methods for Option - bool convToBool(const std::string& val); - char convToChar(const std::string& val); - template Tnum convToNum(const std::string& val); + bool convToBool(const std::string &val); + char convToChar(const std::string &val); + template Tnum convToNum(const std::string &val); // data T _value; // option value @@ -121,24 +126,25 @@ protected: /** * @brief interface for Option class */ -class IOption { +class IOption +{ public: /** * @brief set option value * @param val - value of option in string format * @todo add support for vector */ - virtual void setValue(const std::string& val) = 0; + virtual void setValue(const std::string &val) = 0; /** * @brief get all names of option */ - virtual const std::vector& getNames() const = 0; + virtual const std::vector &getNames() const = 0; /** * @brief get description of option */ - virtual const std::string& getOverview() const = 0; + virtual const std::string &getOverview() const = 0; /** * @brief may option be optional? @@ -148,12 +154,12 @@ public: /** * @brief get valid values for given option */ - virtual const std::vector& getValidVals() const = 0; + virtual const std::vector &getValidVals() const = 0; /** * @brief get separators for option */ - virtual const std::vector& getSeparators() const = 0; + virtual const std::vector &getSeparators() const = 0; /** * @brief function for option verification @@ -178,10 +184,11 @@ public: virtual bool isGrouped() const = 0; // groups for option. Each option can be put in one of these groups - enum class Group { + enum class Group + { none = 0, caffe2 = 1, - onnx = 2 // 'onnx' is currently unused + onnx = 2 // 'onnx' is currently unused }; /** @@ -196,7 +203,7 @@ public: protected: // this array contains name of option groups. It must be synchronized with Group enum - constexpr static const char* const _groupNames[] = {nullptr, "caffe2", "onnx"}; + constexpr static const char *const _groupNames[] = {nullptr, "caffe2", "onnx"}; }; /** @@ -204,12 +211,13 @@ protected: * @tparam T - type of option */ template -class Option final : public OptionType::value>, public IOption { +class Option final : public OptionType::value>, public IOption +{ public: /** * @brief function type for option verification */ - using option_checker_t = void (*)(const Option&); + using option_checker_t = void (*)(const Option &); /** * @brief construct an option @@ -224,48 +232,47 @@ public: * @param enabled - if this option is set to false then it won't be shown for users * @param group - all options can be splitted into groups so this param sets group for option */ - explicit Option(const std::vector& optnames, - const std::string& descr, - const T& default_val = T(), - bool is_optional = false, - const std::vector& vals = std::vector(), + explicit Option(const std::vector &optnames, const std::string &descr, + const T &default_val = T(), bool is_optional = false, + const std::vector &vals = std::vector(), option_checker_t checker = nullptr, - const std::vector& seps = std::vector(), - bool enabled = true, + const std::vector &seps = std::vector(), bool enabled = true, IOption::Group group = IOption::Group::none); // options must not be copyable and assignment - Option(const Option&) = delete; + Option(const Option &) = delete; - Option& operator=(const Option&) = delete; + Option &operator=(const Option &) = delete; /** * @brief overload assignment operator for type */ - template - T& operator=(const Tval& val) { // NOLINT(cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator) + template T &operator=(const Tval &val) + { // NOLINT(cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator) setRawValue(val); return this->getRawValue(); // If not using `this` it won't work } // overridden methods - void setValue(const std::string& val) override; + void setValue(const std::string &val) override; - const std::vector& getNames() const override { return _names; } + const std::vector &getNames() const override { return _names; } - const std::string& getOverview() const override { return _descr; } + const std::string &getOverview() const override { return _descr; } bool isOptional() const override { return _is_optional; } - const std::vector& getValidVals() const override { return _valid_vals; } + const std::vector &getValidVals() const override { return _valid_vals; } - void runCheckerFunc() override { - if (_checker) { + void runCheckerFunc() override + { + if (_checker) + { _checker(*this); } } - const std::vector& getSeparators() const override { return _seps; } + const std::vector &getSeparators() const override { return _seps; } bool isDisabled() const override { return !_is_enabled; } @@ -281,44 +288,46 @@ public: private: // data std::vector _names; // names of the option - std::string _descr; // overview of option + std::string _descr; // overview of option bool _is_optional; std::vector _valid_vals; // option can be initialized only by these values - option_checker_t _checker; // function verifies option and its value - std::vector _seps; // these symbols separate option name and its value + option_checker_t _checker; // function verifies option and its value + std::vector _seps; // these symbols separate option name and its value bool _is_enabled; bool _can_have_several_vals; // can option take several values? - IOption::Group _group; // group for option + IOption::Group _group; // group for option }; /** * @brief this class describes a common command line interface */ -class CommandLine { // NOLINT(cppcoreguidelines-special-member-functions, hicpp-special-member-functions) +class CommandLine +{ // NOLINT(cppcoreguidelines-special-member-functions, hicpp-special-member-functions) public: // prevent copy or assignment - CommandLine(const CommandLine&) = delete; + CommandLine(const CommandLine &) = delete; - CommandLine& operator=(const CommandLine&) = delete; + CommandLine &operator=(const CommandLine &) = delete; /** * @brief singleton method */ - static CommandLine* getParser(); + static CommandLine *getParser(); /** * @brief parse command line option * @param argc - number of command line arguments * @param argv - command line arguments - * @param check_nonoptional - if true then check that all non optional declared options are presented + * @param check_nonoptional - if true then check that all non optional declared options are + * presented */ - void parseCommandLine(int argc, const char** argv, bool check_nonoptional = true); + void parseCommandLine(int argc, const char **argv, bool check_nonoptional = true); /** * @brief register option for parser * @param opt - option */ - void registerOption(IOption* opt); + void registerOption(IOption *opt); private: /** @@ -326,19 +335,19 @@ private: * @param msg - additional user message * @param exit_code - the program is terminated with this code */ - [[noreturn]] void usage(const std::string& msg = "", int exit_code = EXIT_FAILURE); + [[noreturn]] void usage(const std::string &msg = "", int exit_code = EXIT_FAILURE); /** * @brief check that all non optional registered options are passed from command line * @param cmd_args - arguments from command line */ - void checkRegisteredOptions(const std::set& cmd_args); + void checkRegisteredOptions(const std::set &cmd_args); /** * @brief call verification function, if present, for option * @param cmd_args - arguments from command line */ - void checkOptions(const std::set& cmd_args); + void checkOptions(const std::set &cmd_args); /** * @brief find option with `optname` and set `pos` to option value @@ -346,7 +355,7 @@ private: * @return pointer to option * @throw BadOption throw exception if option not found */ - IOption* findOption(const char* optname); + IOption *findOption(const char *optname); /** * @brief figure out option value @@ -356,7 +365,7 @@ private: * @return position in argv where option value begins or empty string if option doesn't have value * @throw BadOption throw exception if value for option is incorrect */ - const char* findOptionValue(const IOption* opt, const char** argv, int cur_argv); + const char *findOptionValue(const IOption *opt, const char **argv, int cur_argv); /** * @brief figure out value for option with multiple values @@ -364,22 +373,23 @@ private: * @param opt_name - option name which taken from command line * @param argv - array of command line arguments * @param val_argv - position in argv for current option value - * @return position in argv where option value begins or nullptr if option doesn't have value anymore + * @return position in argv where option value begins or nullptr if option doesn't have value + * anymore * @throw BadOption throw exception if value for option is incorrect */ - const char* findValueForMultOption(const IOption* opt, - const std::string& opt_name, - const char** argv, int cur_argv); + const char *findValueForMultOption(const IOption *opt, const std::string &opt_name, + const char **argv, int cur_argv); // allow object constructor only for methods CommandLine() = default; // data - std::map _options_name; // map of name -> option - std::vector _options; // options - std::map> _grouped_options; // map of groups: group -> vector of options + std::map _options_name; // map of name -> option + std::vector _options; // options + std::map> + _grouped_options; // map of groups: group -> vector of options std::string _prog_name; // name of program - int _args_num = 0; // number of command line arguments + int _args_num = 0; // number of command line arguments }; // the following functions are helpers for users that declare new options @@ -388,10 +398,11 @@ private: * @param names - name of option, if option has several names then * `names` must be represented by a string separated by a comma */ -std::vector optname(const char* names); +std::vector optname(const char *names); /** @brief convert option overview for Option constructor */ -inline std::string overview(const char* descr) { +inline std::string overview(const char *descr) +{ std::string overview(descr); assert(!overview.empty()); @@ -406,13 +417,13 @@ inline bool optional(bool is_optional) { return is_optional; } * @param vals - valid values of option, if option has several that values then * `vals` must be represented by a string separated by a comma */ -std::vector optvalues(const char* vals); +std::vector optvalues(const char *vals); /** * @brief separators that separate option name and its value * @param seps - chars of separators separated by a comma */ -std::vector separators(const char* seps); +std::vector separators(const char *seps); /** * @param is_shown - if set to false, then option won't be shown in help message @@ -420,18 +431,18 @@ std::vector separators(const char* seps); inline bool showopt(bool is_shown) { return is_shown; } // end of helper functions - // // Implementation of template functions // -template -bool OptionType::convToBool(const std::string& val) { - if (val.empty() || val == "TRUE" || - val == "True" || val == "true" || val == "1") { +template bool OptionType::convToBool(const std::string &val) +{ + if (val.empty() || val == "TRUE" || val == "True" || val == "true" || val == "1") + { return true; } - if (val == "FALSE" || val == "False" || val == "false" || val == "0") { + if (val == "FALSE" || val == "False" || val == "false" || val == "0") + { return false; } @@ -439,12 +450,14 @@ bool OptionType::convToBool(const std::string& val) { } // convToBool -template -char OptionType::convToChar(const std::string& val) { - if (val.length() == 1) { +template char OptionType::convToChar(const std::string &val) +{ + if (val.length() == 1) + { return val[0]; - - } else { + } + else + { throw BadOption("", val); } @@ -452,22 +465,25 @@ char OptionType::convToChar(const std::string& val) { template template -Tnum OptionType::convToNum(const std::string& val) { +Tnum OptionType::convToNum(const std::string &val) +{ Tnum num_val; assert((std::is_same::value || std::is_same::value)); assert((std::numeric_limits::max() < std::numeric_limits::max())); assert(std::numeric_limits::min() >= std::numeric_limits::min()); - try { + try + { num_val = std::is_same::value ? stoull(val) : stoll(val); - - } catch (...) { + } + catch (...) + { throw BadOption("", val); } - if (num_val > std::numeric_limits::max() || - num_val < std::numeric_limits::min()) { + if (num_val > std::numeric_limits::max() || num_val < std::numeric_limits::min()) + { throw BadOption("", val); } @@ -475,19 +491,15 @@ Tnum OptionType::convToNum(const std::string& val) { } // convToNum - template -Option::Option(const std::vector& optnames, - const std::string& descr, - const T& default_val, - bool is_optional, - const std::vector& vals, - option_checker_t checker, - const std::vector& seps, - bool enabled, - IOption::Group group) { +Option::Option(const std::vector &optnames, const std::string &descr, + const T &default_val, bool is_optional, const std::vector &vals, + option_checker_t checker, const std::vector &seps, bool enabled, + IOption::Group group) +{ // save all names - for (const auto& n : optnames) { + for (const auto &n : optnames) + { _names.push_back(n); assert(n[0] == '-' && "option name must start with `-`"); @@ -502,7 +514,8 @@ Option::Option(const std::vector& optnames, #ifndef NDEBUG // check that separators are valid symbols - for (const auto& s : _seps) { + for (const auto &s : _seps) + { assert((s == '=' || s == ':') && "invalid option separators"); } #endif // NDEBUG @@ -516,8 +529,8 @@ Option::Option(const std::vector& optnames, _group = group; - _can_have_several_vals = std::is_same>::value - || std::is_same>::value; + _can_have_several_vals = + std::is_same>::value || std::is_same>::value; assert(!(_can_have_several_vals && !_seps.empty()) && "option with several values can't have separators"); @@ -526,19 +539,18 @@ Option::Option(const std::vector& optnames, } // Option - // // prototypes of option checker functions // -void checkInFile(const Option& in_file); +void checkInFile(const Option &in_file); -void checkOutFile(const Option& out_file); +void checkOutFile(const Option &out_file); -void checkInDir(const Option& dir); +void checkInDir(const Option &dir); -void checkOutDir(const Option& dir); +void checkOutDir(const Option &dir); } // namespace cli } // namespace nnc -#endif //NNCC_COMMANDLINE_H +#endif // NNCC_COMMANDLINE_H diff --git a/compiler/nnc/pass/PassManager.cpp b/compiler/nnc/pass/PassManager.cpp index 1474c15..0b2c065 100644 --- a/compiler/nnc/pass/PassManager.cpp +++ b/compiler/nnc/pass/PassManager.cpp @@ -22,12 +22,14 @@ namespace nnc PassManager::PassManager() = default; -PassManager::~PassManager() { - for (auto& pass : _passes) +PassManager::~PassManager() +{ + for (auto &pass : _passes) pass->cleanup(); } -void PassManager::registerPass(std::unique_ptr pass) { +void PassManager::registerPass(std::unique_ptr pass) +{ _passes.push_back(std::move(pass)); } // registerPass diff --git a/compiler/nnc/passes/acl_soft_backend/AclCppGenerator.cpp b/compiler/nnc/passes/acl_soft_backend/AclCppGenerator.cpp index d51129b..37cffe6 100644 --- a/compiler/nnc/passes/acl_soft_backend/AclCppGenerator.cpp +++ b/compiler/nnc/passes/acl_soft_backend/AclCppGenerator.cpp @@ -25,16 +25,19 @@ #include #include -namespace nnc { +namespace nnc +{ using namespace std; -PassData AclCppCodeGenerator::run(PassData data) { - mir::Graph* g = data; +PassData AclCppCodeGenerator::run(PassData data) +{ + mir::Graph *g = data; assert(g); // Create a directory for generated artifact files. - int res = mkdir(cli::artifactDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); // NOLINT(hicpp-signed-bitwise) + int res = mkdir(cli::artifactDir.c_str(), + S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); // NOLINT(hicpp-signed-bitwise) if (res != 0 && errno != EEXIST) throw AclCppException("Failed to create output directory"); diff --git a/compiler/nnc/passes/acl_soft_backend/AclCppOpGenerator.cpp b/compiler/nnc/passes/acl_soft_backend/AclCppOpGenerator.cpp index 01dad5e..b9258a7 100644 --- a/compiler/nnc/passes/acl_soft_backend/AclCppOpGenerator.cpp +++ b/compiler/nnc/passes/acl_soft_backend/AclCppOpGenerator.cpp @@ -26,16 +26,20 @@ #include -namespace nnc { +namespace nnc +{ using namespace std; using namespace mir; -AclCppOpGenerator::AclCppOpGenerator(const string& name, ostream& par_out) - : _parOut(par_out), _module(name), _constrBlock(nullptr), _infBlock(nullptr), - _clScheduler(AF::id("arm_compute::CLScheduler")) {} +AclCppOpGenerator::AclCppOpGenerator(const string &name, ostream &par_out) + : _parOut(par_out), _module(name), _constrBlock(nullptr), _infBlock(nullptr), + _clScheduler(AF::id("arm_compute::CLScheduler")) +{ +} -const ArtifactModule& AclCppOpGenerator::generate(mir::Graph* g) { +const ArtifactModule &AclCppOpGenerator::generate(mir::Graph *g) +{ // Including headers. _module.addHeaderSysInclude("fstream"); _module.addHeaderInclude("arm_compute/core/Types.h"); @@ -57,11 +61,12 @@ const ArtifactModule& AclCppOpGenerator::generate(mir::Graph* g) { _parIn = _parInVar->use(); string par_file_name = cli::artifactName + ".par"; _constrBlock->call("open", {AF::lit("\"" + par_file_name + "\""), - AF::lit("std::ios_base::in | std::ios_base::binary")}, _parIn); + AF::lit("std::ios_base::in | std::ios_base::binary")}, + _parIn); auto file_fail = _constrBlock->ifCond(AF::call("fail", {}, _parIn)); auto file_fail_block = file_fail->getBlock(); - file_fail_block->addStatement(AF::lit("throw std::string(\"Failed to open file: " + - par_file_name + " for reading\")")); + file_fail_block->addStatement( + AF::lit("throw std::string(\"Failed to open file: " + par_file_name + " for reading\")")); // Traverse the computational graph. g->accept(this); @@ -78,26 +83,26 @@ const ArtifactModule& AclCppOpGenerator::generate(mir::Graph* g) { return _module; } -void AclCppOpGenerator::visit(ops::ConcatOp& op) { - const auto& ir_inputs = op.getInputs(); - const auto* ir_output = op.getOutput(0); +void AclCppOpGenerator::visit(ops::ConcatOp &op) +{ + const auto &ir_inputs = op.getInputs(); + const auto *ir_output = op.getOutput(0); - static const char* axis_names[] = {"arm_compute::DataLayoutDimension::BATCHES", - "arm_compute::DataLayoutDimension::CHANNEL", - "arm_compute::DataLayoutDimension::HEIGHT", - "arm_compute::DataLayoutDimension::WIDTH"}; + static const char *axis_names[] = { + "arm_compute::DataLayoutDimension::BATCHES", "arm_compute::DataLayoutDimension::CHANNEL", + "arm_compute::DataLayoutDimension::HEIGHT", "arm_compute::DataLayoutDimension::WIDTH"}; int axis = op.getAxis(); assert(axis >= 0 && axis < static_cast(sizeof(axis_names) / sizeof(axis_names[0])) && "axis outside this range is not supported in ACL"); - const char* axis_name = axis_names[axis]; + const char *axis_name = axis_names[axis]; auto out = genTensor(ir_output); auto prefix = out->name() + "_concatenate_layer"; auto inputs_var = _constrBlock->var("std::vector", prefix + "_inputs"); auto inputs = inputs_var->use(); - for (const auto& ir_input : ir_inputs) + for (const auto &ir_input : ir_inputs) _constrBlock->call("push_back", {AF::ref(AF::id(tensorName(ir_input.getProducer())))}, inputs); auto layer = genLayer("arm_compute::CLConcatenateLayer", prefix, @@ -107,18 +112,21 @@ void AclCppOpGenerator::visit(ops::ConcatOp& op) { genLayerExecution(layer); } -void AclCppOpGenerator::visit(ops::Conv2DOp& op) { +void AclCppOpGenerator::visit(ops::Conv2DOp &op) +{ genConvolution(op, "arm_compute::CLConvolutionLayer", "_convolution_layer"); } -void AclCppOpGenerator::visit(ops::DepthwiseConv2DOp& op) { +void AclCppOpGenerator::visit(ops::DepthwiseConv2DOp &op) +{ genConvolution(op, "arm_compute::CLDepthwiseConvolutionLayer", "_depthwise_convolution_layer"); } -void AclCppOpGenerator::visit(ops::SoftmaxOp& op) { +void AclCppOpGenerator::visit(ops::SoftmaxOp &op) +{ assert(op.getNumInputs() == 1); - const auto* ir_input = op.getInput(0)->getProducer(); - const auto* ir_output = op.getOutput(0); + const auto *ir_input = op.getInput(0)->getProducer(); + const auto *ir_output = op.getOutput(0); auto in = AF::id(tensorName(ir_input)); @@ -130,7 +138,8 @@ void AclCppOpGenerator::visit(ops::SoftmaxOp& op) { assert(axis == rank - 1); int nof_long_axes = 0; - for (int i = 0; i < rank; ++i) { + for (int i = 0; i < rank; ++i) + { if (ir_output->getShape().dim(i) > 1) ++nof_long_axes; } @@ -143,18 +152,22 @@ void AclCppOpGenerator::visit(ops::SoftmaxOp& op) { shared_ptr output = genTensor(ir_output); auto layer_name_prefix = output->name(); - if (axis == 0) { + if (axis == 0) + { // Simple version: do not need pre and post reshapes. // Apply the softmax operation. auto sm = genLayer("arm_compute::CLSoftmaxLayer", layer_name_prefix + "_softmax_layer", {AF::ref(in), AF::ref(output)}); addToPersistentTensors(output); genLayerExecution(sm); - } else { + } + else + { // TODO refactor this code, it works only with 1 batch // Need to reshape before the Softmax application and after it. - // Then we need two tensors for intermediate results. This is because we do a couple of auxiliary + // Then we need two tensors for intermediate results. This is because we do a couple of + // auxiliary // reshapes: one to transform the input tensor to a unidimensional tensor and the second to // transorm the result of the softmax operation back to the original form. Shape sm_shape(ir_output->getShape()); @@ -166,7 +179,7 @@ void AclCppOpGenerator::visit(ops::SoftmaxOp& op) { // Do the input permutation. auto transp1 = genLayer("arm_compute::CLReshapeLayer", layer_name_prefix + "_transp_layer1", - {AF::ref(in), AF::ref(tmp)}); + {AF::ref(in), AF::ref(tmp)}); addToPersistentTensors(tmp); genLayerExecution(transp1); @@ -178,44 +191,45 @@ void AclCppOpGenerator::visit(ops::SoftmaxOp& op) { // Reshape the output to the original form. auto transp2 = genLayer("arm_compute::CLReshapeLayer", layer_name_prefix + "_transp_layer2", - {AF::ref(tmp2), AF::ref(output)}); + {AF::ref(tmp2), AF::ref(output)}); addToPersistentTensors(output); genLayerExecution(transp2); } } template -shared_ptr -AclCppOpGenerator::genPadStrideInfo(const Op& op, const string& prefix, ArtifactBlock* block) { +shared_ptr AclCppOpGenerator::genPadStrideInfo(const Op &op, const string &prefix, + ArtifactBlock *block) +{ using AF = ArtifactFactory; - const Shape& strides = transposeShape<1, 0>(op.getStrides()); + const Shape &strides = transposeShape<1, 0>(op.getStrides()); assert(strides.rank() == 2); - auto& padding_before = op.getPaddingBefore(); - auto& padding_after = op.getPaddingAfter(); + auto &padding_before = op.getPaddingBefore(); + auto &padding_after = op.getPaddingAfter(); string type_name = "arm_compute::PadStrideInfo"; string var_name = prefix + "_pad_stride_info"; - list> var_init_params = - {AF::lit(to_string(op.getStrides().dim(1))), - AF::lit(to_string(op.getStrides().dim(0))), - AF::lit(to_string(padding_before.at(1))), - AF::lit(to_string(padding_after.at(1))), - AF::lit(to_string(padding_before.at(0))), - AF::lit(to_string(padding_after.at(0))), - AF::lit("arm_compute::DimensionRoundingType::FLOOR")}; + list> var_init_params = { + AF::lit(to_string(op.getStrides().dim(1))), + AF::lit(to_string(op.getStrides().dim(0))), + AF::lit(to_string(padding_before.at(1))), + AF::lit(to_string(padding_after.at(1))), + AF::lit(to_string(padding_before.at(0))), + AF::lit(to_string(padding_after.at(0))), + AF::lit("arm_compute::DimensionRoundingType::FLOOR")}; auto pad_stride_info_var = block->var(type_name, var_name, {}, var_init_params); return pad_stride_info_var; } -shared_ptr -AclCppOpGenerator::genTransposeMIRtoACL(const string& name, - const Shape& input_shape, - const shared_ptr& input) { +shared_ptr AclCppOpGenerator::genTransposeMIRtoACL(const string &name, + const Shape &input_shape, + const shared_ptr &input) +{ Shape transposed_shape = transposeShape<0, 3, 1, 2>(input_shape); shared_ptr transposed_id = genTensor(name, transposed_shape, false); const bool allocate_at_inference = true; @@ -223,10 +237,10 @@ AclCppOpGenerator::genTransposeMIRtoACL(const string& name, return transposed_id; } -shared_ptr -AclCppOpGenerator::genTransposeACLtoMIR(const string& name, - const Shape& input_shape, - const shared_ptr& input) { +shared_ptr AclCppOpGenerator::genTransposeACLtoMIR(const string &name, + const Shape &input_shape, + const shared_ptr &input) +{ Shape transposed_shape = transposeShape<0, 2, 3, 1>(input_shape); shared_ptr transposed_id = genTensor(name, transposed_shape, false); const bool allocate_at_inference = false; @@ -234,14 +248,16 @@ AclCppOpGenerator::genTransposeACLtoMIR(const string& name, return transposed_id; } -void AclCppOpGenerator::visit(ops::PoolOp& op) { +void AclCppOpGenerator::visit(ops::PoolOp &op) +{ assert(op.getNumInputs() == 1); - const auto* ir_input = op.getInput(0)->getProducer(); - const auto* ir_output = op.getOutput(0); + const auto *ir_input = op.getInput(0)->getProducer(); + const auto *ir_output = op.getOutput(0); - const char* pooling_type = nullptr; + const char *pooling_type = nullptr; - switch (op.getPoolingType()) { + switch (op.getPoolingType()) + { case ops::PoolOp::PoolingType::MAX: pooling_type = "arm_compute::PoolingType::MAX"; break; @@ -264,8 +280,7 @@ void AclCppOpGenerator::visit(ops::PoolOp& op) { const string layer_name = output_tensor_name + "_pooling_layer"; - shared_ptr pad_stride_info_var = - genPadStrideInfo(op, layer_name, _constrBlock); + shared_ptr pad_stride_info_var = genPadStrideInfo(op, layer_name, _constrBlock); shared_ptr pad_stride_info = pad_stride_info_var->use(); @@ -273,14 +288,14 @@ void AclCppOpGenerator::visit(ops::PoolOp& op) { shared_ptr kernel_window_var = _constrBlock->var("arm_compute::Size2D", layer_name + "_kernel_window", {}, {AF::lit(to_string(op.getWindowShape().dim(1))), - AF::lit(to_string(op.getWindowShape().dim(0)))}); + AF::lit(to_string(op.getWindowShape().dim(0)))}); shared_ptr kernel_window = kernel_window_var->use(); // Create pooling info: pooling type, kernel info, strides, etc shared_ptr pooling_info_var = _constrBlock->var( - "arm_compute::PoolingLayerInfo", layer_name + "_pooling_info", {}, - {AF::lit(pooling_type), kernel_window, pad_stride_info, - AF::lit(op.getBorderType() == ops::PoolOp::BorderType::EMPTY ? "true" : "false")}); + "arm_compute::PoolingLayerInfo", layer_name + "_pooling_info", {}, + {AF::lit(pooling_type), kernel_window, pad_stride_info, + AF::lit(op.getBorderType() == ops::PoolOp::BorderType::EMPTY ? "true" : "false")}); shared_ptr pooling_info = pooling_info_var->use(); // Generate auxiliary tensor to hold transposed output of pool in NCHW format @@ -289,8 +304,9 @@ void AclCppOpGenerator::visit(ops::PoolOp& op) { genTensor(layer_name + "_out_transpose", transposed_output_shape); // Actual layer creation - shared_ptr layer = genLayer("arm_compute::CLPoolingLayer", layer_name, - {AF::ref(transposed_input), AF::ref(transposed_output), pooling_info}); + shared_ptr layer = + genLayer("arm_compute::CLPoolingLayer", layer_name, + {AF::ref(transposed_input), AF::ref(transposed_output), pooling_info}); genTensorAllocation(_infBlock, transposed_output); genLayerExecution(layer); @@ -301,18 +317,19 @@ void AclCppOpGenerator::visit(ops::PoolOp& op) { genTensorDeallocation(_infBlock, transposed_output); } -void AclCppOpGenerator::visit(ops::FullyConnectedOp& op) { +void AclCppOpGenerator::visit(ops::FullyConnectedOp &op) +{ assert(op.getNumInputs() == 2); - const auto* ir_input = op.getInput(0)->getProducer(); - const auto* ir_weights = op.getInput(1)->getProducer(); - const auto* ir_output = op.getOutput(0); + const auto *ir_input = op.getInput(0)->getProducer(); + const auto *ir_weights = op.getInput(1)->getProducer(); + const auto *ir_output = op.getOutput(0); - auto ir_weights_op = dynamic_cast(ir_weights->getNode()); + auto ir_weights_op = dynamic_cast(ir_weights->getNode()); if (ir_weights_op == nullptr) throw AclCppException("Unsupported operation type"); const TensorVariant ir_weights_tensor = transposeTensor<1, 0>(ir_weights_op->getValue()); - const Shape& ir_weights_shape = ir_weights_tensor.getShape(); + const Shape &ir_weights_shape = ir_weights_tensor.getShape(); // Get the input node tensor id in the DOM. auto in = AF::id(tensorName(ir_input)); @@ -337,30 +354,36 @@ void AclCppOpGenerator::visit(ops::FullyConnectedOp& op) { genLayerExecution(layer); } -void AclCppOpGenerator::visit(ops::GemmOp& /*op*/) { +void AclCppOpGenerator::visit(ops::GemmOp & /*op*/) +{ throw AclCppException("Unimplemented operation: GemmOp"); } -void AclCppOpGenerator::visit(ops::CappedReluOp& op) { +void AclCppOpGenerator::visit(ops::CappedReluOp &op) +{ genActivation(op, "LU_BOUNDED_RELU", op.getCap()); } -void AclCppOpGenerator::visit(ops::InputOp& op) { +void AclCppOpGenerator::visit(ops::InputOp &op) +{ shared_ptr tensor; tensor = genTensor(op.getOutput(0)); addToPersistentTensors(tensor); } // FIXME: temporary solution -static bool shouldSerializeConstant(const ops::ConstantOp& op) { - // Operations from 'self_serializing_ops_to_inputs' serializing tensors with appropriate index themselves, +static bool shouldSerializeConstant(const ops::ConstantOp &op) +{ + // Operations from 'self_serializing_ops_to_inputs' serializing tensors with appropriate index + // themselves, // so we don't serialize them here, also we don't serialize tensors from dangling ConstantOp static std::map self_serializing_ops_to_inputs{ - {Operation::Type::conv2D, 1}, - {Operation::Type::fullyConnected, 1}}; + {Operation::Type::conv2D, 1}, {Operation::Type::fullyConnected, 1}}; - for (const auto* consumer : op.getOutput(0)->getConsumers()) { - auto self_serializing_op_it = self_serializing_ops_to_inputs.find(consumer->getNode()->getType()); + for (const auto *consumer : op.getOutput(0)->getConsumers()) + { + auto self_serializing_op_it = + self_serializing_ops_to_inputs.find(consumer->getNode()->getType()); // Serialize if next_node type not from 'self_serializing_ops_to_inputs' if (self_serializing_op_it == self_serializing_ops_to_inputs.end()) return true; @@ -374,8 +397,10 @@ static bool shouldSerializeConstant(const ops::ConstantOp& op) { return false; } -void AclCppOpGenerator::visit(ops::ConstantOp& op) { - if (shouldSerializeConstant(op)) { +void AclCppOpGenerator::visit(ops::ConstantOp &op) +{ + if (shouldSerializeConstant(op)) + { TensorVariant data = op.getValue(); shared_ptr out = genTensor(op.getOutput(0)); addToPersistentTensors(out); @@ -383,26 +408,27 @@ void AclCppOpGenerator::visit(ops::ConstantOp& op) { } } -void AclCppOpGenerator::visit(ops::ReluOp& op) { - genActivation(op, "RELU"); -} +void AclCppOpGenerator::visit(ops::ReluOp &op) { genActivation(op, "RELU"); } -void AclCppOpGenerator::visit(ops::ReshapeOp& op) { +void AclCppOpGenerator::visit(ops::ReshapeOp &op) +{ assert(op.getNumInputs() == 1); - const auto* ir_input = op.getInput(0)->getProducer(); - const auto* ir_output = op.getOutput(0); + const auto *ir_input = op.getInput(0)->getProducer(); + const auto *ir_output = op.getOutput(0); // Get the id of the input tensor in the generated artifact. auto in = AF::id(tensorName(ir_input)); // Create the output tensor in the DOM and return its id. - const Shape& out_shape = ir_output->getShape(); + const Shape &out_shape = ir_output->getShape(); // This check confirms that we can "safely" reshape data // The only safe configuration of output shape is (1...1, N, 1 ... 1) bool found_non_one = false; - for (int32_t i = 0; i < out_shape.rank(); ++i) { - if (out_shape.dim(i) != 1) { + for (int32_t i = 0; i < out_shape.rank(); ++i) + { + if (out_shape.dim(i) != 1) + { if (found_non_one) throw AclCppException("Unsupported result of reshape"); found_non_one = true; @@ -418,19 +444,22 @@ void AclCppOpGenerator::visit(ops::ReshapeOp& op) { genLayerExecution(layer); } -void AclCppOpGenerator::visit(mir::ops::SliceOp& /*op*/) { +void AclCppOpGenerator::visit(mir::ops::SliceOp & /*op*/) +{ throw AclCppException("Unimplemented operation: SliceOp"); } -void AclCppOpGenerator::visit(ops::BatchNormOp& /*op*/) { +void AclCppOpGenerator::visit(ops::BatchNormOp & /*op*/) +{ // Not supported in our framework, but present in ACL API. throw AclCppException("Not supported in inference yet."); } -void AclCppOpGenerator::visit(ops::DropoutOp& op) { +void AclCppOpGenerator::visit(ops::DropoutOp &op) +{ assert(op.getNumInputs() == 1); - const auto* ir_input = op.getInput(0)->getProducer(); - const auto* ir_output = op.getOutput(0); + const auto *ir_input = op.getInput(0)->getProducer(); + const auto *ir_output = op.getOutput(0); // Just copy input tensor to the output one. @@ -443,22 +472,23 @@ void AclCppOpGenerator::visit(ops::DropoutOp& op) { _constrBlock->var("arm_compute::CLTensor&", out->name(), {}, {in}); } -void AclCppOpGenerator::visit(ops::TanhOp& op) { - genActivation(op, "TANH"); -} +void AclCppOpGenerator::visit(ops::TanhOp &op) { genActivation(op, "TANH"); } -void AclCppOpGenerator::visit(ops::DeConv2DOp& op) { +void AclCppOpGenerator::visit(ops::DeConv2DOp &op) +{ genConvolution(op, "arm_compute::CLDeconvolutionLayer", "_deconvolution_layer"); } -void AclCppOpGenerator::visit(ops::EluOp& /*op*/) { +void AclCppOpGenerator::visit(ops::EluOp & /*op*/) +{ throw AclCppException("EluOp not supported by the ACL library yet."); } -void AclCppOpGenerator::visit(ops::PadOp& op) { +void AclCppOpGenerator::visit(ops::PadOp &op) +{ assert(op.getNumInputs() == 1); - const auto* ir_input = op.getInput(0)->getProducer(); - const auto* ir_output = op.getOutput(0); + const auto *ir_input = op.getInput(0)->getProducer(); + const auto *ir_output = op.getOutput(0); // Get the id of the input tensor. auto input = AF::id(tensorName(ir_input)); @@ -471,40 +501,44 @@ void AclCppOpGenerator::visit(ops::PadOp& op) { auto prefix = out->name() + "_pad_layer"; auto pad_list_decl = _constrBlock->var("arm_compute::PaddingList", prefix + "_pads"); auto pad_list = pad_list_decl->use(); - for (int i = 0; i < op.getNumDim(); ++i) { + for (int i = 0; i < op.getNumDim(); ++i) + { auto pad_var = _constrBlock->var("arm_compute::PaddingInfo", prefix + "_pad_" + to_string(i), - {}, - {AF::lit(to_string(op.getPaddingForDim(i).first)), - AF::lit(to_string(op.getPaddingForDim(i).second))}); + {}, {AF::lit(to_string(op.getPaddingForDim(i).first)), + AF::lit(to_string(op.getPaddingForDim(i).second))}); auto pad = pad_var->use(); _constrBlock->call("push_back", {pad}, pad_list); } // Generate PadLayer - auto layer = genLayer("arm_compute::CLPadLayer", prefix, - {AF::ref(input), AF::ref(out), pad_list}); + auto layer = + genLayer("arm_compute::CLPadLayer", prefix, {AF::ref(input), AF::ref(out), pad_list}); genLayerExecution(layer); } template -void AclCppOpGenerator::genConvolution(Op& op, const string& acl_func_name, const string& suffix) { - const auto* ir_input = op.getInput(0)->getProducer(); - const auto* ir_weights = op.getInput(1)->getProducer(); - const auto* ir_output = op.getOutput(0); +void AclCppOpGenerator::genConvolution(Op &op, const string &acl_func_name, const string &suffix) +{ + const auto *ir_input = op.getInput(0)->getProducer(); + const auto *ir_weights = op.getInput(1)->getProducer(); + const auto *ir_output = op.getOutput(0); - auto ir_weights_op = dynamic_cast(ir_weights->getNode()); + auto ir_weights_op = dynamic_cast(ir_weights->getNode()); if (ir_weights_op == nullptr) throw AclCppException("Unsupported operation type"); auto ir_weights_tensor = ir_weights_op->getValue(); - if (op.getType() == Operation::Type::conv2D) { + if (op.getType() == Operation::Type::conv2D) + { // [Co, Hk, Wk, Ci] -> [Co, Ci, Hk, Wk]. ir_weights_tensor = transposeTensor<0, 3, 1, 2>(ir_weights_tensor); - } else { + } + else + { ir_weights_tensor = transposeTensor<3, 2, 0, 1>(ir_weights_tensor); } - const Shape& ir_weights_shape = ir_weights_tensor.getShape(); + const Shape &ir_weights_shape = ir_weights_tensor.getShape(); // get output tensor name that is used as base for other names const string output_tensor_name = tensorName(ir_output); @@ -535,12 +569,13 @@ void AclCppOpGenerator::genConvolution(Op& op, const string& acl_func_name, cons // The parameter for the conv_layer.config(&in, &weights, nullptr, &out, pad_stride_info) // function call. - list> config_params{AF::ref(transposed_input), - AF::ref(weights), AF::lit("nullptr"), - AF::ref(transposed_output), pad_stride_info}; + list> config_params{AF::ref(transposed_input), AF::ref(weights), + AF::lit("nullptr"), AF::ref(transposed_output), + pad_stride_info}; // Add to additional parameters for deconvolution. - if (op.getType() == Operation::Type::deConv2D) { + if (op.getType() == Operation::Type::deConv2D) + { config_params.push_back(AF::lit("0")); config_params.push_back(AF::lit("0")); } @@ -562,11 +597,12 @@ void AclCppOpGenerator::genConvolution(Op& op, const string& acl_func_name, cons genTensorDeallocation(_infBlock, transposed_output); } -void AclCppOpGenerator::genActivation(const Operation& op, const std::string& activation_name, - float a, float b) { +void AclCppOpGenerator::genActivation(const Operation &op, const std::string &activation_name, + float a, float b) +{ assert(op.getNumInputs() == 1); - const auto* ir_input = op.getInput(0)->getProducer(); - const auto* ir_output = op.getOutput(0); + const auto *ir_input = op.getInput(0)->getProducer(); + const auto *ir_output = op.getOutput(0); // Get the id of the input tensor. auto in = AF::id(tensorName(ir_input)); @@ -580,9 +616,9 @@ void AclCppOpGenerator::genActivation(const Operation& op, const std::string& ac // constructor. This instance profide information about the concrete activation function, // like: ReLU, Tanh etc and two optional parameter (alpha and betha) needed by some activations. auto activation_info_var = _constrBlock->var( - "arm_compute::ActivationLayerInfo", prefix + "_activation_info", {}, - {AF::lit("arm_compute::ActivationLayerInfo::ActivationFunction::" + activation_name), - AF::lit(to_string(a)), AF::lit(to_string(b))}); + "arm_compute::ActivationLayerInfo", prefix + "_activation_info", {}, + {AF::lit("arm_compute::ActivationLayerInfo::ActivationFunction::" + activation_name), + AF::lit(to_string(a)), AF::lit(to_string(b))}); auto activation_info = activation_info_var->use(); // Create an instance of the CLActivationLayer class as a member of the artifact class. @@ -592,11 +628,12 @@ void AclCppOpGenerator::genActivation(const Operation& op, const std::string& ac genLayerExecution(layer); } -shared_ptr AclCppOpGenerator::genAddition(const string& prefix, size_t index, - const Shape& ir_shape, - const std::shared_ptr& in1, - const std::shared_ptr& in2, - std::shared_ptr out) { +shared_ptr AclCppOpGenerator::genAddition(const string &prefix, size_t index, + const Shape &ir_shape, + const std::shared_ptr &in1, + const std::shared_ptr &in2, + std::shared_ptr out) +{ string operation_name = prefix + "_" + to_string(index); // Create the output tensor in the DOM or reuse the out, if it is not nullptr - that is for the // last element in the handled sequence. @@ -618,11 +655,12 @@ shared_ptr AclCppOpGenerator::genAddition(const string& prefix, size return out; } -shared_ptr AclCppOpGenerator::genMultiplication(const string& prefix, size_t index, - const Shape& ir_shape, - const shared_ptr& in1, - const shared_ptr& in2, - shared_ptr out) { +shared_ptr AclCppOpGenerator::genMultiplication(const string &prefix, size_t index, + const Shape &ir_shape, + const shared_ptr &in1, + const shared_ptr &in2, + shared_ptr out) +{ string operation_name = prefix + "_" + to_string(index); // Create the output tensor in the DOM or reuse the out, if it is not nullptr - that is for the @@ -651,7 +689,7 @@ shared_ptr AclCppOpGenerator::genMultiplication(const string& prefix // Create an instance of the CLArithmeticDivision class as a member of the artifact class. auto arithmetic_div_layer_var1 = _artifactClass->var(false, "arm_compute::CLArithmeticDivision", - operation_name + "_arithmetic_div_layer_1"); + operation_name + "_arithmetic_div_layer_1"); auto arithmetic_div_layer1 = arithmetic_div_layer_var1->use(); // Generate the call: arithmetic_div_layer1.configure(&unit, &in2, &tmp); @@ -678,18 +716,21 @@ shared_ptr AclCppOpGenerator::genMultiplication(const string& prefix return out; } -string AclCppOpGenerator::tensorName(const Operation::Output* ir_tensor) const { +string AclCppOpGenerator::tensorName(const Operation::Output *ir_tensor) const +{ string tensor_name; // TODO Use the tensor name instead of the operation name. - const auto& op_name = ir_tensor->getNode()->getName(); + const auto &op_name = ir_tensor->getNode()->getName(); - if (!op_name.empty()) { + if (!op_name.empty()) + { tensor_name = "_" + op_name; - replace_if(tensor_name.begin(), - tensor_name.end(), - [](char c) { return std::isalnum(c) == 0; }, '_'); - } else { + replace_if(tensor_name.begin(), tensor_name.end(), [](char c) { return std::isalnum(c) == 0; }, + '_'); + } + else + { tensor_name = "tensor_" + to_string(ir_tensor->getNode()->getId()); } @@ -698,11 +739,12 @@ string AclCppOpGenerator::tensorName(const Operation::Output* ir_tensor) const { template std::shared_ptr -AclCppOpGenerator::genVectorInitializedVar(ArtifactBlock* block, const string& type, - const string& name, const vector & init) { +AclCppOpGenerator::genVectorInitializedVar(ArtifactBlock *block, const string &type, + const string &name, const vector &init) +{ list> dims; - for (const auto& v : init) + for (const auto &v : init) dims.push_back(AF::lit(to_string(v))); auto shape_var = block->var(type, name, {}, dims); @@ -710,12 +752,13 @@ AclCppOpGenerator::genVectorInitializedVar(ArtifactBlock* block, const string& t return shape_id; } -shared_ptr AclCppOpGenerator::genTensor(const string& name, - const Shape& ir_shape, - bool gen_accessor) { +shared_ptr AclCppOpGenerator::genTensor(const string &name, const Shape &ir_shape, + bool gen_accessor) +{ auto id = AF::id(name); - if (_tensorNames.insert(name).second) { + if (_tensorNames.insert(name).second) + { _artifactClass->var(false, "arm_compute::CLTensor", name); vector shape_vectorized; @@ -724,12 +767,13 @@ shared_ptr AclCppOpGenerator::genTensor(const string& name, for (int i = 0; i < ir_shape.rank(); ++i) shape_vectorized.push_back(ir_shape.dim(-i - 1)); - const char* type_name = "arm_compute::TensorShape"; + const char *type_name = "arm_compute::TensorShape"; shared_ptr shape = genVectorInitializedVar(_constrBlock, type_name, name + "_shape", shape_vectorized); _constrBlock->call("initializeTensor", {id, shape}); - if (gen_accessor) { + if (gen_accessor) + { auto f = _artifactClass->func(true, "arm_compute::CLTensor&", "get" + name); auto b = f->getBlock(); b->ret(id); @@ -739,24 +783,28 @@ shared_ptr AclCppOpGenerator::genTensor(const string& name, return id; } -shared_ptr AclCppOpGenerator::genTensor(const Operation::Output* ir_tensor) { +shared_ptr AclCppOpGenerator::genTensor(const Operation::Output *ir_tensor) +{ return genTensor(tensorName(ir_tensor), ir_tensor->getShape(), !ir_tensor->getNode()->getName().empty()); } -void AclCppOpGenerator::genNamed(Graph* graph) { - const auto& inputs = graph->getInputs(); - if (inputs.size() == 1) { - const auto* input_op = inputs[0]; +void AclCppOpGenerator::genNamed(Graph *graph) +{ + const auto &inputs = graph->getInputs(); + if (inputs.size() == 1) + { + const auto *input_op = inputs[0]; auto f = _artifactClass->func(true, "arm_compute::CLTensor&", "getInput"); auto b = f->getBlock(); auto id = AF::id(tensorName(input_op->getOutput(0))); b->ret(id); } - const auto& outputs = graph->getOutputs(); - if (outputs.size() == 1) { - const auto* output_op = outputs[0]; + const auto &outputs = graph->getOutputs(); + if (outputs.size() == 1) + { + const auto *output_op = outputs[0]; auto f = _artifactClass->func(true, "arm_compute::CLTensor&", "getOutput"); auto b = f->getBlock(); auto id = AF::id(tensorName(output_op->getInput(0)->getProducer())); @@ -764,20 +812,23 @@ void AclCppOpGenerator::genNamed(Graph* graph) { } } -void AclCppOpGenerator::serializeTensor(const shared_ptr& tensor_id, - const TensorVariant& ir_tensor) { +void AclCppOpGenerator::serializeTensor(const shared_ptr &tensor_id, + const TensorVariant &ir_tensor) +{ serializeIRTensor(ir_tensor); _serializations.push_back(tensor_id); } -void AclCppOpGenerator::serializeIRTensor(const TensorVariant& tensor) { - const Shape& shape = tensor.getShape(); +void AclCppOpGenerator::serializeIRTensor(const TensorVariant &tensor) +{ + const Shape &shape = tensor.getShape(); Index coords; coords.resize(shape.rank()); Index dimensions; dimensions.resize(shape.rank()); - for (int i = 0; i < shape.rank(); ++i) { + for (int i = 0; i < shape.rank(); ++i) + { coords.at(i) = 0; dimensions.at(i) = shape.dim(i); } @@ -786,74 +837,86 @@ void AclCppOpGenerator::serializeIRTensor(const TensorVariant& tensor) { _parOut.write(tensor.atOffset(0), data_size); } -void AclCppOpGenerator::genDeserializations() { - for (auto& tensor : _serializations) +void AclCppOpGenerator::genDeserializations() +{ + for (auto &tensor : _serializations) _constrBlock->call("deserializeTensor", {_parIn, tensor}); } -void AclCppOpGenerator::genFillings() { +void AclCppOpGenerator::genFillings() +{ for (auto f : _fillings) _constrBlock->call("fillTensor", {f.first, AF::lit(f.second)}); } -void AclCppOpGenerator::fillTensor(const shared_ptr& tensor_id, const string& val) { +void AclCppOpGenerator::fillTensor(const shared_ptr &tensor_id, const string &val) +{ _fillings.emplace_back(make_pair(tensor_id, val)); } -void AclCppOpGenerator::visit(ops::SqueezeOp& /*op*/) { +void AclCppOpGenerator::visit(ops::SqueezeOp & /*op*/) +{ throw AclCppException("Unimplemented operation: Squeeze"); } -void AclCppOpGenerator::visit(ops::SqrtOp& /*op*/) { +void AclCppOpGenerator::visit(ops::SqrtOp & /*op*/) +{ throw AclCppException("Unimplemented operation: Sqrt"); } -void AclCppOpGenerator::addToPersistentTensors(const std::shared_ptr& tensor_id) { +void AclCppOpGenerator::addToPersistentTensors(const std::shared_ptr &tensor_id) +{ _persistent_tensors.push_back(tensor_id); } shared_ptr -AclCppOpGenerator::genTensorAllocation(ArtifactBlock* block, - const shared_ptr& tensor) { +AclCppOpGenerator::genTensorAllocation(ArtifactBlock *block, const shared_ptr &tensor) +{ return block->call("allocate", {}, AF::call("allocator", {}, tensor), ArtifactCallType::ref); } shared_ptr -AclCppOpGenerator::genTensorDeallocation(ArtifactBlock* block, - const shared_ptr& tensor) { +AclCppOpGenerator::genTensorDeallocation(ArtifactBlock *block, const shared_ptr &tensor) +{ return block->call("free", {}, AF::call("allocator", {}, tensor), ArtifactCallType::ref); } -void AclCppOpGenerator::genPersistentTensorAllocations() { - for (auto& tensor : _persistent_tensors) +void AclCppOpGenerator::genPersistentTensorAllocations() +{ + for (auto &tensor : _persistent_tensors) genTensorAllocation(_constrBlock, tensor); } shared_ptr -AclCppOpGenerator::genLayer(const string& layer_type, const string& layer_name, - const list>& config_params) { +AclCppOpGenerator::genLayer(const string &layer_type, const string &layer_name, + const list> &config_params) +{ auto layer_var = _artifactClass->var(false, layer_type, layer_name); auto layer = layer_var->use(); _constrBlock->call("configure", config_params, layer); return layer; } -void AclCppOpGenerator::genLayerExecution(const shared_ptr& layer_id) { +void AclCppOpGenerator::genLayerExecution(const shared_ptr &layer_id) +{ _infBlock->call("run", {}, layer_id); } -void AclCppOpGenerator::visit(mir::ops::ResizeOp& /*op*/) { +void AclCppOpGenerator::visit(mir::ops::ResizeOp & /*op*/) +{ throw AclCppException("Unimplemented operation: Resize"); } -void AclCppOpGenerator::visit(mir::ops::ReduceOp& /*op*/) { +void AclCppOpGenerator::visit(mir::ops::ReduceOp & /*op*/) +{ throw AclCppException("Unimplemented operation: ReduceOp"); } -void AclCppOpGenerator::genTranspose(const std::shared_ptr& input, - const std::shared_ptr& output, - const std::vector& mir_perm, - bool allocate_at_inference) { +void AclCppOpGenerator::genTranspose(const std::shared_ptr &input, + const std::shared_ptr &output, + const std::vector &mir_perm, + bool allocate_at_inference) +{ // acl 18.8 opencl implementation supports only 3 types of permutation: // in mir (0, 3, 1, 2), in acl(axes are in reverse order) (1, 2, 0) @@ -861,7 +924,7 @@ void AclCppOpGenerator::genTranspose(const std::shared_ptr& inp // in mir (2, 3, 1, 0), in acl (3, 2, 0, 1) // so here we try to transform mir transpose into one acl supports - const string& out_name = output->name(); + const string &out_name = output->name(); vector acl_perm; if (mir_perm == vector{0, 3, 1, 2}) @@ -874,9 +937,8 @@ void AclCppOpGenerator::genTranspose(const std::shared_ptr& inp throw AclCppException("Unsupported transpose sequence in operation " + out_name); // Create operation parameter containing permutation vector - shared_ptr perm_vector = - genVectorInitializedVar(_constrBlock, "arm_compute::PermutationVector", - out_name + "_perm_param", acl_perm); + shared_ptr perm_vector = genVectorInitializedVar( + _constrBlock, "arm_compute::PermutationVector", out_name + "_perm_param", acl_perm); // Instantiate the CLPermute object. string layer_name = out_name + "_transpose_layer"; @@ -889,14 +951,15 @@ void AclCppOpGenerator::genTranspose(const std::shared_ptr& inp genLayerExecution(layer); } -void AclCppOpGenerator::visit(mir::ops::TransposeOp& op) { +void AclCppOpGenerator::visit(mir::ops::TransposeOp &op) +{ assert(op.getNumInputs() == 1); - const auto* ir_input = op.getInput(0)->getProducer(); - const auto* ir_output = op.getOutput(0); + const auto *ir_input = op.getInput(0)->getProducer(); + const auto *ir_output = op.getOutput(0); // Get the input node tensor id in the DOM. shared_ptr input = AF::id(tensorName(ir_input)); - const vector& mir_axis_order = op.getAxisOrder(); + const vector &mir_axis_order = op.getAxisOrder(); // Create the output tensor in the DOM. if (ir_output->getShape().rank() != 4) @@ -908,19 +971,20 @@ void AclCppOpGenerator::visit(mir::ops::TransposeOp& op) { genTranspose(input, output, mir_axis_order, false); } -void AclCppOpGenerator::visit(mir::ops::GatherOp& /*op*/) { +void AclCppOpGenerator::visit(mir::ops::GatherOp & /*op*/) +{ throw AclCppException("Unimplemented operation: GatherOp"); } -void AclCppOpGenerator::visit(ops::SigmoidOp& op) { - genActivation(op, "LOGISTIC"); -} +void AclCppOpGenerator::visit(ops::SigmoidOp &op) { genActivation(op, "LOGISTIC"); } -void AclCppOpGenerator::visit(mir::ops::LeakyReluOp& op) { +void AclCppOpGenerator::visit(mir::ops::LeakyReluOp &op) +{ genActivation(op, "LEAKY_RELU", op.getAlpha()); } -void AclCppOpGenerator::visit(mir::ops::OutputOp& /*op*/) { +void AclCppOpGenerator::visit(mir::ops::OutputOp & /*op*/) +{ // No-op. } diff --git a/compiler/nnc/passes/acl_soft_backend/AclCppOpGenerator.h b/compiler/nnc/passes/acl_soft_backend/AclCppOpGenerator.h index fe4ae83..9636c7e 100644 --- a/compiler/nnc/passes/acl_soft_backend/AclCppOpGenerator.h +++ b/compiler/nnc/passes/acl_soft_backend/AclCppOpGenerator.h @@ -27,59 +27,61 @@ #include -namespace nnc { +namespace nnc +{ /** * @brief Implements the visitor for the model IR which generates the DOM description * translated to C++ source/header files by the ACL soft backend code generators. */ -class AclCppOpGenerator : public mir::IVisitor { +class AclCppOpGenerator : public mir::IVisitor +{ public: - AclCppOpGenerator(const std::string& name, std::ostream& par_out); + AclCppOpGenerator(const std::string &name, std::ostream &par_out); /** * @brief The main interface function to the class. Convers the model IR to the DOM. * @param g - pointer the model IR graph. * @return - reference to the top-level DOM entity. */ - const ArtifactModule& generate(mir::Graph* g); + const ArtifactModule &generate(mir::Graph *g); /** * @brief Implementations of the IVisitor visitors. * @param op */ - void visit(mir::ops::AddOp& op) override; - void visit(mir::ops::BatchNormOp& op) override; - void visit(mir::ops::CappedReluOp& op) override; - void visit(mir::ops::ConcatOp& op) override; - void visit(mir::ops::ConstantOp& op) override; - void visit(mir::ops::Conv2DOp& op) override; - void visit(mir::ops::DeConv2DOp& op) override; - void visit(mir::ops::DepthwiseConv2DOp& op) override; - void visit(mir::ops::DivOp& op) override; - void visit(mir::ops::DropoutOp& op) override; - void visit(mir::ops::EluOp& op) override; - void visit(mir::ops::FullyConnectedOp& op) override; - void visit(mir::ops::GatherOp& op) override; - void visit(mir::ops::GemmOp& op) override; - void visit(mir::ops::InputOp& op) override; - void visit(mir::ops::LeakyReluOp& op) override; - void visit(mir::ops::MaxOp& op) override; - void visit(mir::ops::MulOp& op) override; - void visit(mir::ops::OutputOp& op) override; - void visit(mir::ops::PadOp& op) override; - void visit(mir::ops::PoolOp& op) override; - void visit(mir::ops::ReduceOp& op) override; - void visit(mir::ops::ReluOp& op) override; - void visit(mir::ops::ReshapeOp& op) override; - void visit(mir::ops::ResizeOp& op) override; - void visit(mir::ops::SigmoidOp& op) override; - void visit(mir::ops::SliceOp& op) override; - void visit(mir::ops::SoftmaxOp& op) override; - void visit(mir::ops::SqrtOp& op) override; - void visit(mir::ops::SqueezeOp& op) override; - void visit(mir::ops::SubOp& op) override; - void visit(mir::ops::TanhOp& op) override; - void visit(mir::ops::TransposeOp& op) override; + void visit(mir::ops::AddOp &op) override; + void visit(mir::ops::BatchNormOp &op) override; + void visit(mir::ops::CappedReluOp &op) override; + void visit(mir::ops::ConcatOp &op) override; + void visit(mir::ops::ConstantOp &op) override; + void visit(mir::ops::Conv2DOp &op) override; + void visit(mir::ops::DeConv2DOp &op) override; + void visit(mir::ops::DepthwiseConv2DOp &op) override; + void visit(mir::ops::DivOp &op) override; + void visit(mir::ops::DropoutOp &op) override; + void visit(mir::ops::EluOp &op) override; + void visit(mir::ops::FullyConnectedOp &op) override; + void visit(mir::ops::GatherOp &op) override; + void visit(mir::ops::GemmOp &op) override; + void visit(mir::ops::InputOp &op) override; + void visit(mir::ops::LeakyReluOp &op) override; + void visit(mir::ops::MaxOp &op) override; + void visit(mir::ops::MulOp &op) override; + void visit(mir::ops::OutputOp &op) override; + void visit(mir::ops::PadOp &op) override; + void visit(mir::ops::PoolOp &op) override; + void visit(mir::ops::ReduceOp &op) override; + void visit(mir::ops::ReluOp &op) override; + void visit(mir::ops::ReshapeOp &op) override; + void visit(mir::ops::ResizeOp &op) override; + void visit(mir::ops::SigmoidOp &op) override; + void visit(mir::ops::SliceOp &op) override; + void visit(mir::ops::SoftmaxOp &op) override; + void visit(mir::ops::SqrtOp &op) override; + void visit(mir::ops::SqueezeOp &op) override; + void visit(mir::ops::SubOp &op) override; + void visit(mir::ops::TanhOp &op) override; + void visit(mir::ops::TransposeOp &op) override; private: using AF = ArtifactFactory; @@ -91,9 +93,9 @@ private: * @param input id of input tensor * @return Id of result tensor */ - std::shared_ptr genTransposeMIRtoACL(const std::string& name, - const mir::Shape& input_shape, - const std::shared_ptr& input); + std::shared_ptr genTransposeMIRtoACL(const std::string &name, + const mir::Shape &input_shape, + const std::shared_ptr &input); /** * @brief generate transpose NCHW -> NHWC @@ -102,9 +104,9 @@ private: * @param input id of input tensor * @return Id of result tensor */ - std::shared_ptr genTransposeACLtoMIR(const std::string& name, - const mir::Shape& input_shape, - const std::shared_ptr& input); + std::shared_ptr genTransposeACLtoMIR(const std::string &name, + const mir::Shape &input_shape, + const std::shared_ptr &input); /** * @brief Generate DOM for PadStrideInfo object @@ -115,14 +117,14 @@ private: * @return generated variable */ template - std::shared_ptr - genPadStrideInfo(const Op& op, const std::string& prefix, ArtifactBlock* block); + std::shared_ptr genPadStrideInfo(const Op &op, const std::string &prefix, + ArtifactBlock *block); /** * @brief The common part of the convolution and the depthwise convolution. */ template - void genConvolution(Op& op, const std::string& acl_func_name, const std::string& suffix); + void genConvolution(Op &op, const std::string &acl_func_name, const std::string &suffix); /** * @brief Generates different types of activation functions: ReLU, Tanh etc. @@ -131,9 +133,8 @@ private: * LINEAR, TANH. * @param b - betha parameter used by some activation functions: LINEAR, LU_BOUNDED_RELU, TANH. */ - void - genActivation(const mir::Operation& op, const std::string& activation_name, float a = 0, - float b = 0); + void genActivation(const mir::Operation &op, const std::string &activation_name, float a = 0, + float b = 0); /** * @brief Used to generate a binary addition operation in handling of the elementwise. @@ -152,10 +153,10 @@ private: * to the left of and including the in2 term, or the operation out if in2 was * the last term in the sequence. */ - std::shared_ptr genAddition(const std::string& prefix, size_t index, - const mir::Shape& ir_shape, - const std::shared_ptr& in1, - const std::shared_ptr& in2, + std::shared_ptr genAddition(const std::string &prefix, size_t index, + const mir::Shape &ir_shape, + const std::shared_ptr &in1, + const std::shared_ptr &in2, std::shared_ptr out = nullptr); /** @@ -178,16 +179,16 @@ private: * elements to the left of and including the in2 term, or the operation out if * in2 was the last term in the sequence. */ - std::shared_ptr genMultiplication(const std::string& prefix, size_t index, - const mir::Shape& ir_shape, - const std::shared_ptr& in1, - const std::shared_ptr& in2, + std::shared_ptr genMultiplication(const std::string &prefix, size_t index, + const mir::Shape &ir_shape, + const std::shared_ptr &in1, + const std::shared_ptr &in2, std::shared_ptr out = nullptr); /** * @brief Generates a unique name for the tensor. */ - std::string tensorName(const mir::Operation::Output* ir_tensor) const; + std::string tensorName(const mir::Operation::Output *ir_tensor) const; /** * @brief Generates variables tensor shape in DOM. @@ -197,10 +198,9 @@ private: * @return - a DOM identifier for the created shape. */ template - std::shared_ptr genVectorInitializedVar(ArtifactBlock* block, - const std::string& type, - const std::string& name, - const std::vector& init); + std::shared_ptr genVectorInitializedVar(ArtifactBlock *block, const std::string &type, + const std::string &name, + const std::vector &init); /** * @brief Generates a DOM tensor. @@ -210,7 +210,7 @@ private: * in the artifact class. * @return - a DOM identifier for the created tensor. */ - std::shared_ptr genTensor(const std::string& name, const mir::Shape& ir_shape, + std::shared_ptr genTensor(const std::string &name, const mir::Shape &ir_shape, bool gen_accessor = false); /** @@ -218,37 +218,38 @@ private: * @param ir_tensor - the ModelIR tensor. * @return - a DOM identifier for the created tensor. */ - std::shared_ptr genTensor(const mir::Operation::Output* ir_tensor); + std::shared_ptr genTensor(const mir::Operation::Output *ir_tensor); /** - * @brief generate transposing operation, @p mir_perm contains dimensions in MIR order (batch has index 0) + * @brief generate transposing operation, @p mir_perm contains dimensions in MIR order (batch has + * index 0) * @param input id of input tensor * @param output id out output tensor * @param mir_perm new order of dimensions */ - void genTranspose(const std::shared_ptr& input, - const std::shared_ptr& output, - const std::vector& mir_perm, - bool allocate_at_inference); + void genTranspose(const std::shared_ptr &input, + const std::shared_ptr &output, + const std::vector &mir_perm, bool allocate_at_inference); /** * @brief Generates accessors for the input/output tensors. * @param graph - the ModelIR graph. */ - void genNamed(mir::Graph* graph); + void genNamed(mir::Graph *graph); /** * @brief Schedule a tensor serialization. * @param tensor_id - an artifact ID of the tensor. * @param ir_tensor - the IR source of the tensor. */ - void serializeTensor(const std::shared_ptr& tensor_id, const mir::TensorVariant& ir_tensor); + void serializeTensor(const std::shared_ptr &tensor_id, + const mir::TensorVariant &ir_tensor); /** * @brief Serialize an IR tensor in a file. * @param tensor - tensor to serialize. */ - void serializeIRTensor(const mir::TensorVariant& tensor); + void serializeIRTensor(const mir::TensorVariant &tensor); /** * @brief Generate the deserialization calls in right places in the artifact. @@ -265,13 +266,13 @@ private: * @param tensor_id - ID of the tensor. * @param val - its value. */ - void fillTensor(const std::shared_ptr& tensor_id, const std::string& val); + void fillTensor(const std::shared_ptr &tensor_id, const std::string &val); /** * @brief Schedule the tensor allocation in the artifact constructor. * @param tensor_id - ID of the scheduled tensor. */ - void addToPersistentTensors(const std::shared_ptr& tensor_id); + void addToPersistentTensors(const std::shared_ptr &tensor_id); /** * @brief Generate allocation of tensor @@ -279,7 +280,7 @@ private: * @param tensor Id of tensor to allocate */ std::shared_ptr - genTensorAllocation(ArtifactBlock* block, const std::shared_ptr& tensor); + genTensorAllocation(ArtifactBlock *block, const std::shared_ptr &tensor); /** * @brief Generate deallocation of tensor @@ -287,7 +288,7 @@ private: * @param tensor Id of tensor to deallocate */ std::shared_ptr - genTensorDeallocation(ArtifactBlock* block, const std::shared_ptr& tensor); + genTensorDeallocation(ArtifactBlock *block, const std::shared_ptr &tensor); /** * @brief Generate all the scheduled tensor allocations. @@ -301,14 +302,15 @@ private: * @param config_params - input/output tensor names and the other configuration information. * @return - generated tensor ID. */ - std::shared_ptr genLayer(const std::string& layer_type, const std::string& layer_name, - const std::list>& config_params); + std::shared_ptr + genLayer(const std::string &layer_type, const std::string &layer_name, + const std::list> &config_params); /** * @brief Generate the layer run() call. * @param layer_id - layer ID. */ - void genLayerExecution(const std::shared_ptr& layer_id); + void genLayerExecution(const std::shared_ptr &layer_id); /** * @brief All named tensors names. @@ -318,7 +320,7 @@ private: /** * @brief The stream for tensors serialization. */ - std::ostream& _parOut; + std::ostream &_parOut; /** * @brief The whole artifact module in the DOM. @@ -338,12 +340,12 @@ private: /** * @brief The constuctor block of DOM instructions. */ - ArtifactBlock* _constrBlock; + ArtifactBlock *_constrBlock; /** * @brief The inference function block of DOM instruction. */ - ArtifactBlock* _infBlock; + ArtifactBlock *_infBlock; /** * @brief The variable describing the input stream for tensors deserialization. @@ -366,7 +368,8 @@ private: std::list> _persistent_tensors; /** - * @brief Tensors which are serialized from the Model IR and need to be deserialized in the artifact. + * @brief Tensors which are serialized from the Model IR and need to be deserialized in the + * artifact. */ std::list> _serializations; diff --git a/compiler/nnc/passes/acl_soft_backend/ArtifactGeneratorCppCode.cpp b/compiler/nnc/passes/acl_soft_backend/ArtifactGeneratorCppCode.cpp index 7e2c27c..d9605f1 100644 --- a/compiler/nnc/passes/acl_soft_backend/ArtifactGeneratorCppCode.cpp +++ b/compiler/nnc/passes/acl_soft_backend/ArtifactGeneratorCppCode.cpp @@ -23,43 +23,45 @@ using namespace std; -namespace nnc { +namespace nnc +{ -ArtifactGeneratorCppCode::ArtifactGeneratorCppCode(ostream& out) : _out(out) { -} +ArtifactGeneratorCppCode::ArtifactGeneratorCppCode(ostream &out) : _out(out) {} -void ArtifactGeneratorCppCode::visit(const ArtifactLiteral* node) { - _out << node->getValue(); -} +void ArtifactGeneratorCppCode::visit(const ArtifactLiteral *node) { _out << node->getValue(); } -void ArtifactGeneratorCppCode::visit(const ArtifactId* node) { - _out << node->name(); -} +void ArtifactGeneratorCppCode::visit(const ArtifactId *node) { _out << node->name(); } -void ArtifactGeneratorCppCode::visit(const ArtifactRef* node) { +void ArtifactGeneratorCppCode::visit(const ArtifactRef *node) +{ _out << "&"; node->obj()->accept(this); } -void ArtifactGeneratorCppCode::visit(const ArtifactDeref* node) { +void ArtifactGeneratorCppCode::visit(const ArtifactDeref *node) +{ _out << "*"; node->obj()->accept(this); } -void ArtifactGeneratorCppCode::visit(const ArtifactVariable* node) { +void ArtifactGeneratorCppCode::visit(const ArtifactVariable *node) +{ _out << node->typeName() << " " << node->name(); - for (const auto& d : node->getDimensions()) { + for (const auto &d : node->getDimensions()) + { _out << "["; d->accept(this); _out << "]"; } - if (!node->getInitializers().empty()) { + if (!node->getInitializers().empty()) + { _out << "("; bool add_comma = false; - for (const auto& i : node->getInitializers()) { + for (const auto &i : node->getInitializers()) + { if (add_comma) _out << ", "; @@ -71,10 +73,12 @@ void ArtifactGeneratorCppCode::visit(const ArtifactVariable* node) { } } -void ArtifactGeneratorCppCode::visit(const ArtifactFunctionCall* node) { - static const char* call_type_str[] = {".", "->", "::"}; +void ArtifactGeneratorCppCode::visit(const ArtifactFunctionCall *node) +{ + static const char *call_type_str[] = {".", "->", "::"}; - if (node->on()) { + if (node->on()) + { node->on()->accept(this); _out << call_type_str[static_cast(node->callType())]; } @@ -83,7 +87,8 @@ void ArtifactGeneratorCppCode::visit(const ArtifactFunctionCall* node) { _out << "("; bool add_comma = false; - for (const auto& par : node->paramList()) { + for (const auto &par : node->paramList()) + { if (add_comma) _out << ", "; @@ -94,52 +99,57 @@ void ArtifactGeneratorCppCode::visit(const ArtifactFunctionCall* node) { _out << ")"; } -void ArtifactGeneratorCppCode::visit(const ArtifactUnaryExpr* node) { +void ArtifactGeneratorCppCode::visit(const ArtifactUnaryExpr *node) +{ // The trailing space is intended in new and delete! - static const char* un_op_str[] = {"++", "--", "new ", "delete ", "++", "--"}; + static const char *un_op_str[] = {"++", "--", "new ", "delete ", "++", "--"}; - if (node->getOp() < ArtifactUnOp::postIncr) { + if (node->getOp() < ArtifactUnOp::postIncr) + { _out << un_op_str[static_cast(node->getOp())]; node->getExpr()->accept(this); - } else { + } + else + { node->getExpr()->accept(this); _out << un_op_str[static_cast(node->getOp())]; } } -void ArtifactGeneratorCppCode::visit(const ArtifactBinaryExpr* node) { - static const char* bin_op_str[] = {"==", "!=", "<", "<=", ">", ">=", "=", "+", "-", "*", "/", - "+=", "-=", "*=", "/="}; +void ArtifactGeneratorCppCode::visit(const ArtifactBinaryExpr *node) +{ + static const char *bin_op_str[] = {"==", "!=", "<", "<=", ">", ">=", "=", "+", + "-", "*", "/", "+=", "-=", "*=", "/="}; node->getLeft()->accept(this); _out << " " << bin_op_str[static_cast(node->getOp())] << " "; node->getRight()->accept(this); } -void ArtifactGeneratorCppCode::visit(const ArtifactIndex* node) { +void ArtifactGeneratorCppCode::visit(const ArtifactIndex *node) +{ node->getExpr()->accept(this); _out << "["; node->getInd()->accept(this); _out << "]"; } -void ArtifactGeneratorCppCode::visit(const ArtifactRet* node) { +void ArtifactGeneratorCppCode::visit(const ArtifactRet *node) +{ _out << "return "; node->expr()->accept(this); } -void ArtifactGeneratorCppCode::visit(const ArtifactBreak* /*node*/) { - _out << "break"; -} +void ArtifactGeneratorCppCode::visit(const ArtifactBreak * /*node*/) { _out << "break"; } -void ArtifactGeneratorCppCode::visit(const ArtifactCont* /*node*/) { - _out << "continue"; -} +void ArtifactGeneratorCppCode::visit(const ArtifactCont * /*node*/) { _out << "continue"; } -void ArtifactGeneratorCppCode::visit(const ArtifactBlock* node) { +void ArtifactGeneratorCppCode::visit(const ArtifactBlock *node) +{ _out << " {" << endl; ++_ind; - for (const auto& st : node->getStatements()) { + for (const auto &st : node->getStatements()) + { _out << _ind; st->accept(this); @@ -151,7 +161,8 @@ void ArtifactGeneratorCppCode::visit(const ArtifactBlock* node) { _out << _ind << "}" << endl; } -void ArtifactGeneratorCppCode::visit(const ArtifactForLoop* node) { +void ArtifactGeneratorCppCode::visit(const ArtifactForLoop *node) +{ _out << "for("; if (node->getInit()) @@ -171,31 +182,37 @@ void ArtifactGeneratorCppCode::visit(const ArtifactForLoop* node) { node->getBlock()->accept(this); } -void ArtifactGeneratorCppCode::visit(const ArtifactIf* node) { +void ArtifactGeneratorCppCode::visit(const ArtifactIf *node) +{ _out << "if("; node->getCond()->accept(this); _out << ")"; node->getBlock()->accept(this); - if (!node->getElseBlock()->getStatements().empty()) { + if (!node->getElseBlock()->getStatements().empty()) + { _out << _ind << "else"; node->getElseBlock()->accept(this); } } -void ArtifactGeneratorCppCode::visit(const ArtifactFunction* /*node*/) { +void ArtifactGeneratorCppCode::visit(const ArtifactFunction * /*node*/) +{ // TODO implement this function } -void ArtifactGeneratorCppCode::visit(const ArtifactClass* node) { +void ArtifactGeneratorCppCode::visit(const ArtifactClass *node) +{ // Generate a public default constructor here. _out << node->name() << "::" << node->name() << "()"; - if (!node->privateVariables().empty()) { + if (!node->privateVariables().empty()) + { _out << " : "; bool add_delim = false; - for (const auto& v : node->privateVariables()) { + for (const auto &v : node->privateVariables()) + { if (add_delim) _out << ",\n"; @@ -204,25 +221,27 @@ void ArtifactGeneratorCppCode::visit(const ArtifactClass* node) { } } - //TODO add constructors of public variables + // TODO add constructors of public variables node->getConstrBlock()->accept(this); _out << endl; // Then generate the other stuff. - for (const auto& e : node->publicFunctions()) + for (const auto &e : node->publicFunctions()) e->accept(this); - for (const auto& e : node->privateFunctions()) + for (const auto &e : node->privateFunctions()) e->accept(this); } -void ArtifactGeneratorCppCode::visit(const ArtifactClassVariable* node) { +void ArtifactGeneratorCppCode::visit(const ArtifactClassVariable *node) +{ _out << node->name() << "("; bool add_comma = false; - for (const auto& i : node->getInitializers()) { + for (const auto &i : node->getInitializers()) + { if (add_comma) _out << ", "; @@ -233,7 +252,8 @@ void ArtifactGeneratorCppCode::visit(const ArtifactClassVariable* node) { _out << ")"; } -void ArtifactGeneratorCppCode::visit(const ArtifactClassFunction* node) { +void ArtifactGeneratorCppCode::visit(const ArtifactClassFunction *node) +{ _out << node->getRetTypeName(); if (!node->getRetTypeName().empty()) @@ -242,7 +262,8 @@ void ArtifactGeneratorCppCode::visit(const ArtifactClassFunction* node) { _out << node->owner()->name() << "::" << node->name() << "("; bool add_comma = false; - for (const auto& p : node->getParameters()) { + for (const auto &p : node->getParameters()) + { if (add_comma) _out << ", "; @@ -255,16 +276,17 @@ void ArtifactGeneratorCppCode::visit(const ArtifactClassFunction* node) { _out << endl; } -void ArtifactGeneratorCppCode::visit(const ArtifactModule* node) { +void ArtifactGeneratorCppCode::visit(const ArtifactModule *node) +{ _out << "#include \"" << node->name() << ".h\"" << endl << endl; - for (const auto& i : node->sourceSysIncludes()) + for (const auto &i : node->sourceSysIncludes()) _out << "#include <" << i << ">" << endl; if (!node->sourceSysIncludes().empty()) _out << endl; - for (const auto& i : node->sourceIncludes()) + for (const auto &i : node->sourceIncludes()) _out << "#include \"" << i << "\"" << endl; if (!node->sourceIncludes().empty()) @@ -273,7 +295,7 @@ void ArtifactGeneratorCppCode::visit(const ArtifactModule* node) { _out.write(AclArtifactUtilities, sizeof(AclArtifactUtilities)); _out << endl; - for (const auto& e : node->entities()) + for (const auto &e : node->entities()) e->accept(this); } diff --git a/compiler/nnc/passes/acl_soft_backend/ArtifactGeneratorCppCode.h b/compiler/nnc/passes/acl_soft_backend/ArtifactGeneratorCppCode.h index 9cef771..9394750 100644 --- a/compiler/nnc/passes/acl_soft_backend/ArtifactGeneratorCppCode.h +++ b/compiler/nnc/passes/acl_soft_backend/ArtifactGeneratorCppCode.h @@ -28,34 +28,35 @@ namespace nnc /** * @brief The ACL C++ artifact source code producer. */ -class ArtifactGeneratorCppCode : public IArtifactGenerator { +class ArtifactGeneratorCppCode : public IArtifactGenerator +{ public: - explicit ArtifactGeneratorCppCode(std::ostream& out); - - void visit(const ArtifactLiteral* node) override; - void visit(const ArtifactId* node) override; - void visit(const ArtifactRef* node) override; - void visit(const ArtifactDeref* node) override; - void visit(const ArtifactVariable* node) override; - void visit(const ArtifactFunctionCall* node) override; - void visit(const ArtifactUnaryExpr* node) override; - void visit(const ArtifactBinaryExpr* node) override; - void visit(const ArtifactIndex* node) override; - void visit(const ArtifactRet* node) override; - void visit(const ArtifactBreak* node) override; - void visit(const ArtifactCont* node) override; - void visit(const ArtifactBlock* node) override; - void visit(const ArtifactForLoop* node) override; - void visit(const ArtifactIf* node) override; - void visit(const ArtifactFunction* node) override; - void visit(const ArtifactClass* node) override; - void visit(const ArtifactClassVariable* node) override; - void visit(const ArtifactClassFunction* node) override; - void visit(const ArtifactModule* node) override; + explicit ArtifactGeneratorCppCode(std::ostream &out); + + void visit(const ArtifactLiteral *node) override; + void visit(const ArtifactId *node) override; + void visit(const ArtifactRef *node) override; + void visit(const ArtifactDeref *node) override; + void visit(const ArtifactVariable *node) override; + void visit(const ArtifactFunctionCall *node) override; + void visit(const ArtifactUnaryExpr *node) override; + void visit(const ArtifactBinaryExpr *node) override; + void visit(const ArtifactIndex *node) override; + void visit(const ArtifactRet *node) override; + void visit(const ArtifactBreak *node) override; + void visit(const ArtifactCont *node) override; + void visit(const ArtifactBlock *node) override; + void visit(const ArtifactForLoop *node) override; + void visit(const ArtifactIf *node) override; + void visit(const ArtifactFunction *node) override; + void visit(const ArtifactClass *node) override; + void visit(const ArtifactClassVariable *node) override; + void visit(const ArtifactClassFunction *node) override; + void visit(const ArtifactModule *node) override; private: - std::ostream& _out; - ArtifactIndent _ind; + std::ostream &_out; + ArtifactIndent _ind; }; } // namespace nnc diff --git a/compiler/nnc/passes/acl_soft_backend/ArtifactGeneratorCppDecl.cpp b/compiler/nnc/passes/acl_soft_backend/ArtifactGeneratorCppDecl.cpp index 2c0067e..95f3703 100644 --- a/compiler/nnc/passes/acl_soft_backend/ArtifactGeneratorCppDecl.cpp +++ b/compiler/nnc/passes/acl_soft_backend/ArtifactGeneratorCppDecl.cpp @@ -21,59 +21,60 @@ using namespace std; -namespace nnc { +namespace nnc +{ -ArtifactGeneratorCppDecl::ArtifactGeneratorCppDecl(ostream& out) : _out(out) { -} +ArtifactGeneratorCppDecl::ArtifactGeneratorCppDecl(ostream &out) : _out(out) {} -void ArtifactGeneratorCppDecl::visit(const ArtifactLiteral* node) { - _out << node->getValue(); -} +void ArtifactGeneratorCppDecl::visit(const ArtifactLiteral *node) { _out << node->getValue(); } -void ArtifactGeneratorCppDecl::visit(const ArtifactId* node) { - _out << node->name(); -} +void ArtifactGeneratorCppDecl::visit(const ArtifactId *node) { _out << node->name(); } -void ArtifactGeneratorCppDecl::visit(const ArtifactRef* node) { +void ArtifactGeneratorCppDecl::visit(const ArtifactRef *node) +{ _out << "&"; node->obj()->accept(this); } -void ArtifactGeneratorCppDecl::visit(const ArtifactDeref* node) { +void ArtifactGeneratorCppDecl::visit(const ArtifactDeref *node) +{ _out << "*"; node->obj()->accept(this); } -void ArtifactGeneratorCppDecl::visit(const ArtifactVariable* node) { +void ArtifactGeneratorCppDecl::visit(const ArtifactVariable *node) +{ _out << node->typeName() << " " << node->name(); } -void ArtifactGeneratorCppDecl::visit(const ArtifactFunctionCall* /*node*/) {} +void ArtifactGeneratorCppDecl::visit(const ArtifactFunctionCall * /*node*/) {} -void ArtifactGeneratorCppDecl::visit(const ArtifactUnaryExpr* /*node*/) {} +void ArtifactGeneratorCppDecl::visit(const ArtifactUnaryExpr * /*node*/) {} -void ArtifactGeneratorCppDecl::visit(const ArtifactBinaryExpr* /*node*/) {} +void ArtifactGeneratorCppDecl::visit(const ArtifactBinaryExpr * /*node*/) {} -void ArtifactGeneratorCppDecl::visit(const ArtifactIndex* /*node*/) {} +void ArtifactGeneratorCppDecl::visit(const ArtifactIndex * /*node*/) {} -void ArtifactGeneratorCppDecl::visit(const ArtifactRet* /*node*/) {} +void ArtifactGeneratorCppDecl::visit(const ArtifactRet * /*node*/) {} -void ArtifactGeneratorCppDecl::visit(const ArtifactBreak* /*node*/) {} +void ArtifactGeneratorCppDecl::visit(const ArtifactBreak * /*node*/) {} -void ArtifactGeneratorCppDecl::visit(const ArtifactCont* /*node*/) {} +void ArtifactGeneratorCppDecl::visit(const ArtifactCont * /*node*/) {} -void ArtifactGeneratorCppDecl::visit(const ArtifactBlock* /*node*/) {} +void ArtifactGeneratorCppDecl::visit(const ArtifactBlock * /*node*/) {} -void ArtifactGeneratorCppDecl::visit(const ArtifactForLoop* /*node*/) {} +void ArtifactGeneratorCppDecl::visit(const ArtifactForLoop * /*node*/) {} -void ArtifactGeneratorCppDecl::visit(const ArtifactIf* /*node*/) {} +void ArtifactGeneratorCppDecl::visit(const ArtifactIf * /*node*/) {} -void ArtifactGeneratorCppDecl::visit(const ArtifactFunction* node) { +void ArtifactGeneratorCppDecl::visit(const ArtifactFunction *node) +{ _out << node->getRetTypeName() << " " << node->name() << "("; bool add_comma = false; - for (const auto& par : node->getParameters()) { + for (const auto &par : node->getParameters()) + { if (add_comma) _out << ", "; @@ -84,7 +85,8 @@ void ArtifactGeneratorCppDecl::visit(const ArtifactFunction* node) { _out << ");"; } -void ArtifactGeneratorCppDecl::visit(const ArtifactClass* node) { +void ArtifactGeneratorCppDecl::visit(const ArtifactClass *node) +{ _out << "class " << node->name() << " {" << endl; _out << "public:" << endl; ++_ind; @@ -94,14 +96,16 @@ void ArtifactGeneratorCppDecl::visit(const ArtifactClass* node) { // Then generate the other stuff. - for (const auto& e : node->publicFunctions()) { + for (const auto &e : node->publicFunctions()) + { _out << _ind; e->accept(this); } _out << endl << "private:" << endl; - for (const auto& e : node->privateFunctions()) { + for (const auto &e : node->privateFunctions()) + { _out << _ind; e->accept(this); } @@ -111,7 +115,8 @@ void ArtifactGeneratorCppDecl::visit(const ArtifactClass* node) { // TODO add public variables - for (const auto& e : node->privateVariables()) { + for (const auto &e : node->privateVariables()) + { _out << _ind; e->accept(this); } @@ -120,11 +125,13 @@ void ArtifactGeneratorCppDecl::visit(const ArtifactClass* node) { _out << "};" << endl; } -void ArtifactGeneratorCppDecl::visit(const ArtifactClassVariable* node) { +void ArtifactGeneratorCppDecl::visit(const ArtifactClassVariable *node) +{ _out << node->typeName() << " " << node->name() << ";" << endl; } -void ArtifactGeneratorCppDecl::visit(const ArtifactClassFunction* node) { +void ArtifactGeneratorCppDecl::visit(const ArtifactClassFunction *node) +{ _out << node->getRetTypeName(); if (!node->getRetTypeName().empty()) @@ -133,7 +140,8 @@ void ArtifactGeneratorCppDecl::visit(const ArtifactClassFunction* node) { _out << node->name() << "("; bool add_comma = false; - for (const auto& p : node->getParameters()) { + for (const auto &p : node->getParameters()) + { if (add_comma) _out << ", "; @@ -144,20 +152,21 @@ void ArtifactGeneratorCppDecl::visit(const ArtifactClassFunction* node) { _out << ");" << endl; } -void ArtifactGeneratorCppDecl::visit(const ArtifactModule* node) { - for (const auto& i : node->headerSysIncludes()) +void ArtifactGeneratorCppDecl::visit(const ArtifactModule *node) +{ + for (const auto &i : node->headerSysIncludes()) _out << "#include <" << i << ">" << endl; if (!node->headerSysIncludes().empty()) _out << endl; - for (const auto& i : node->headerIncludes()) + for (const auto &i : node->headerIncludes()) _out << "#include \"" << i << "\"" << endl; if (!node->headerIncludes().empty()) _out << endl; - for (const auto& e : node->entities()) + for (const auto &e : node->entities()) e->accept(this); } diff --git a/compiler/nnc/passes/acl_soft_backend/ArtifactGeneratorCppDecl.h b/compiler/nnc/passes/acl_soft_backend/ArtifactGeneratorCppDecl.h index 9c6a38a..aef8df9 100644 --- a/compiler/nnc/passes/acl_soft_backend/ArtifactGeneratorCppDecl.h +++ b/compiler/nnc/passes/acl_soft_backend/ArtifactGeneratorCppDecl.h @@ -28,33 +28,34 @@ namespace nnc /** * @brief The ACL C++ artifact header file producer. */ -class ArtifactGeneratorCppDecl : public IArtifactGenerator { +class ArtifactGeneratorCppDecl : public IArtifactGenerator +{ public: - explicit ArtifactGeneratorCppDecl(std::ostream& out); - - void visit(const ArtifactLiteral* node) override; - void visit(const ArtifactId* node) override; - void visit(const ArtifactRef* node) override; - void visit(const ArtifactDeref* node) override; - void visit(const ArtifactVariable* node) override; - void visit(const ArtifactFunctionCall* node) override; - void visit(const ArtifactUnaryExpr* node) override; - void visit(const ArtifactBinaryExpr* node) override; - void visit(const ArtifactIndex* node) override; - void visit(const ArtifactRet* node) override; - void visit(const ArtifactBreak* node) override; - void visit(const ArtifactCont* node) override; - void visit(const ArtifactBlock* node) override; - void visit(const ArtifactForLoop* node) override; - void visit(const ArtifactIf* node) override; - void visit(const ArtifactFunction* node) override; - void visit(const ArtifactClass* node) override; - void visit(const ArtifactClassVariable* node) override; - void visit(const ArtifactClassFunction* node) override; - void visit(const ArtifactModule* node) override; + explicit ArtifactGeneratorCppDecl(std::ostream &out); + + void visit(const ArtifactLiteral *node) override; + void visit(const ArtifactId *node) override; + void visit(const ArtifactRef *node) override; + void visit(const ArtifactDeref *node) override; + void visit(const ArtifactVariable *node) override; + void visit(const ArtifactFunctionCall *node) override; + void visit(const ArtifactUnaryExpr *node) override; + void visit(const ArtifactBinaryExpr *node) override; + void visit(const ArtifactIndex *node) override; + void visit(const ArtifactRet *node) override; + void visit(const ArtifactBreak *node) override; + void visit(const ArtifactCont *node) override; + void visit(const ArtifactBlock *node) override; + void visit(const ArtifactForLoop *node) override; + void visit(const ArtifactIf *node) override; + void visit(const ArtifactFunction *node) override; + void visit(const ArtifactClass *node) override; + void visit(const ArtifactClassVariable *node) override; + void visit(const ArtifactClassFunction *node) override; + void visit(const ArtifactModule *node) override; private: - std::ostream& _out; + std::ostream &_out; ArtifactIndent _ind; }; diff --git a/compiler/nnc/passes/acl_soft_backend/ArtifactIndent.h b/compiler/nnc/passes/acl_soft_backend/ArtifactIndent.h index 3cb5156..b241443 100644 --- a/compiler/nnc/passes/acl_soft_backend/ArtifactIndent.h +++ b/compiler/nnc/passes/acl_soft_backend/ArtifactIndent.h @@ -20,21 +20,25 @@ #include #include -namespace nnc { +namespace nnc +{ /** * @brief Used by code and declaration generators to indent generated text. */ -class ArtifactIndent { +class ArtifactIndent +{ public: ArtifactIndent() : _level(0), _step(2) {} - ArtifactIndent& operator++() { + ArtifactIndent &operator++() + { _level += _step; return *this; } - ArtifactIndent& operator--() { + ArtifactIndent &operator--() + { _level -= _step; return *this; } @@ -46,7 +50,8 @@ private: int _step; }; -inline std::ostream& operator<<(std::ostream& out, const ArtifactIndent& ind) { +inline std::ostream &operator<<(std::ostream &out, const ArtifactIndent &ind) +{ if (ind.level() > 0) out << std::string(ind.level(), ' '); diff --git a/compiler/nnc/passes/acl_soft_backend/ArtifactModel.cpp b/compiler/nnc/passes/acl_soft_backend/ArtifactModel.cpp index d9e52cc..8888697 100644 --- a/compiler/nnc/passes/acl_soft_backend/ArtifactModel.cpp +++ b/compiler/nnc/passes/acl_soft_backend/ArtifactModel.cpp @@ -16,93 +16,101 @@ #include "ArtifactModel.h" -namespace nnc { +namespace nnc +{ using namespace std; // ArtifactFunctionCall implementation ArtifactFunctionCall::ArtifactFunctionCall(string func_name, list> param_list, - shared_ptr on, - ArtifactCallType call_type) : - _funcName(std::move(func_name)), _callType(call_type), - _on(std::move(on)), _paramList(std::move(param_list)) { + shared_ptr on, ArtifactCallType call_type) + : _funcName(std::move(func_name)), _callType(call_type), _on(std::move(on)), + _paramList(std::move(param_list)) +{ } // ArtifactBlock implementation. -shared_ptr ArtifactBlock::var( - const string& type_name, - const string& var_name, const list>& dimensions, - const list>& initializers) { +shared_ptr +ArtifactBlock::var(const string &type_name, const string &var_name, + const list> &dimensions, + const list> &initializers) +{ auto var = make_shared(type_name, var_name, dimensions, initializers); _statements.push_back(var); return var; } -shared_ptr ArtifactBlock::call( - const string& func_name, - const list>& param_list, - shared_ptr call_on, ArtifactCallType call_type) { - auto func_call = make_shared(func_name, param_list, - call_on, call_type); +shared_ptr +ArtifactBlock::call(const string &func_name, const list> ¶m_list, + shared_ptr call_on, ArtifactCallType call_type) +{ + auto func_call = make_shared(func_name, param_list, call_on, call_type); _statements.push_back(func_call); return func_call; } -shared_ptr ArtifactBlock::ret(shared_ptr expr) { +shared_ptr ArtifactBlock::ret(shared_ptr expr) +{ auto ret = make_shared(expr); _statements.push_back(ret); return ret; } -shared_ptr ArtifactBlock::brk() { +shared_ptr ArtifactBlock::brk() +{ auto brk = make_shared(); _statements.push_back(brk); return brk; } -shared_ptr ArtifactBlock::cont() { +shared_ptr ArtifactBlock::cont() +{ auto cont = make_shared(); _statements.push_back(cont); return cont; } -shared_ptr ArtifactBlock::forLoop( - shared_ptr init, - shared_ptr cond, shared_ptr iter) { +shared_ptr ArtifactBlock::forLoop(shared_ptr init, + shared_ptr cond, + shared_ptr iter) +{ auto loop = make_shared(init, cond, iter); _statements.push_back(loop); return loop; } -shared_ptr ArtifactBlock::ifCond(shared_ptr cond) { +shared_ptr ArtifactBlock::ifCond(shared_ptr cond) +{ auto ifb = make_shared(cond); _statements.push_back(ifb); return ifb; } -shared_ptr ArtifactBlock::un(ArtifactUnOp op, - shared_ptr expr) { +shared_ptr ArtifactBlock::un(ArtifactUnOp op, shared_ptr expr) +{ auto un = make_shared(op, expr); _statements.push_back(un); return un; } -shared_ptr ArtifactBlock::bin( - ArtifactBinOp op, - shared_ptr left, shared_ptr right) { +shared_ptr ArtifactBlock::bin(ArtifactBinOp op, shared_ptr left, + shared_ptr right) +{ auto bin = make_shared(op, left, right); _statements.push_back(bin); return bin; } -shared_ptr ArtifactBlock::heapNew(shared_ptr expr) { +shared_ptr ArtifactBlock::heapNew(shared_ptr expr) +{ auto heap_new = make_shared(ArtifactUnOp::heapNew, expr); _statements.push_back(heap_new); return heap_new; } -shared_ptr ArtifactBlock::heapFree(shared_ptr expr) { +shared_ptr ArtifactBlock::heapFree(shared_ptr expr) +{ auto heap_del = make_shared(ArtifactUnOp::heapFree, expr); _statements.push_back(heap_del); return heap_del; diff --git a/compiler/nnc/passes/acl_soft_backend/ArtifactModel.h b/compiler/nnc/passes/acl_soft_backend/ArtifactModel.h index fa9a6ee..106c9be 100644 --- a/compiler/nnc/passes/acl_soft_backend/ArtifactModel.h +++ b/compiler/nnc/passes/acl_soft_backend/ArtifactModel.h @@ -25,7 +25,8 @@ #include "IArtifactGenerator.h" -namespace nnc { +namespace nnc +{ /** * @todo FIXME: remove the identical accept() function implementations! @@ -39,16 +40,18 @@ namespace nnc { * @brief Indicates how object on which call is made is treated. * In C++ syntax syntax: '.', '->', '::' */ -enum class ArtifactCallType { - obj, // '.' - ref, // '->' - scope // '::' +enum class ArtifactCallType +{ + obj, // '.' + ref, // '->' + scope // '::' }; /** * @brief The base class of the whole artifact entities hierarchy. */ -class ArtifactEntity { +class ArtifactEntity +{ public: virtual ~ArtifactEntity() = default; @@ -60,7 +63,7 @@ public: * @brief This is the core function of each artifact entity and * is implemented by all concrete classes in the hierarchy. */ - virtual void accept(IArtifactGenerator* g) const = 0; + virtual void accept(IArtifactGenerator *g) const = 0; protected: ArtifactEntity() = default; @@ -78,34 +81,34 @@ public: * Returns the identifier name. * @return the identifier name. */ - const std::string& name() const { return _name; } + const std::string &name() const { return _name; } private: - std::string _name; + std::string _name; }; /** * @brief Basic class for all expressions: identifiers, function calls, references etc. */ -class ArtifactExpr : public ArtifactEntity { +class ArtifactExpr : public ArtifactEntity +{ }; /** * @brief Represents literals which should go to the artifact source code as is. */ -class ArtifactLiteral : public ArtifactExpr { +class ArtifactLiteral : public ArtifactExpr +{ public: explicit ArtifactLiteral(std::string value) : _value(std::move(value)) {} - void accept(IArtifactGenerator* g) const override { - g->visit(this); - } + void accept(IArtifactGenerator *g) const override { g->visit(this); } /** * Returns the literal value. * @return the literal value. */ - const std::string& getValue() const { return _value; } + const std::string &getValue() const { return _value; } private: std::string _value; @@ -114,16 +117,15 @@ private: /** * @brief Type of objects which can be used to reference named entities by their names. */ -class ArtifactId : public ArtifactExpr { +class ArtifactId : public ArtifactExpr +{ public: explicit ArtifactId(std::string id) : _id(std::move(id)) {} - explicit ArtifactId(const ArtifactNamed* named) : _id(named->name()) {} + explicit ArtifactId(const ArtifactNamed *named) : _id(named->name()) {} - void accept(IArtifactGenerator* g) const override { - g->visit(this); - } + void accept(IArtifactGenerator *g) const override { g->visit(this); } - const std::string& name() const { return _id; } + const std::string &name() const { return _id; } private: std::string _id; @@ -132,13 +134,12 @@ private: /** * @brief Represents an entity with semantics like C/C++ address of (&) operator. */ -class ArtifactRef : public ArtifactExpr { +class ArtifactRef : public ArtifactExpr +{ public: explicit ArtifactRef(std::shared_ptr ref) : _ref(std::move(ref)) {} - void accept(IArtifactGenerator* g) const override { - g->visit(this); - } + void accept(IArtifactGenerator *g) const override { g->visit(this); } std::shared_ptr obj() const { return _ref; } @@ -149,13 +150,12 @@ private: /** * @brief Represents an entity with semantics of C/C++ dereference (*) operator. */ -class ArtifactDeref : public ArtifactExpr { +class ArtifactDeref : public ArtifactExpr +{ public: explicit ArtifactDeref(std::shared_ptr ref) : _ref(std::move(ref)) {} - void accept(IArtifactGenerator* g) const override { - g->visit(this); - } + void accept(IArtifactGenerator *g) const override { g->visit(this); } std::shared_ptr obj() const { return _ref; } @@ -166,19 +166,17 @@ private: /** * @brief Represents a function call. */ -class ArtifactFunctionCall : public ArtifactExpr { +class ArtifactFunctionCall : public ArtifactExpr +{ public: - ArtifactFunctionCall(std::string func_name, - std::list> param_list, + ArtifactFunctionCall(std::string func_name, std::list> param_list, std::shared_ptr on = nullptr, ArtifactCallType call_type = ArtifactCallType::obj); - void accept(IArtifactGenerator* g) const override { - g->visit(this); - } + void accept(IArtifactGenerator *g) const override { g->visit(this); } - const std::string& funcName() const { return _funcName; } - const std::list>& paramList() const { return _paramList; } + const std::string &funcName() const { return _funcName; } + const std::list> ¶mList() const { return _paramList; } std::shared_ptr on() const { return _on; } ArtifactCallType callType() const { return _callType; } @@ -192,7 +190,8 @@ private: /** * @brief Used for the ArtifactUnaryExpr. */ -enum class ArtifactUnOp { +enum class ArtifactUnOp +{ preIncr, preDecr, heapNew, @@ -201,15 +200,16 @@ enum class ArtifactUnOp { postDecr }; -class ArtifactUnaryExpr : public ArtifactExpr { +class ArtifactUnaryExpr : public ArtifactExpr +{ public: - ArtifactUnaryExpr(ArtifactUnOp op, std::shared_ptr expr) : - _op(op), _expr(std::move(expr)) {} - - void accept(IArtifactGenerator* g) const override { - g->visit(this); + ArtifactUnaryExpr(ArtifactUnOp op, std::shared_ptr expr) + : _op(op), _expr(std::move(expr)) + { } + void accept(IArtifactGenerator *g) const override { g->visit(this); } + ArtifactUnOp getOp() const { return _op; } std::shared_ptr getExpr() const { return _expr; } @@ -221,7 +221,8 @@ private: /** * @brief Used for the ArtifactBinaryExpr. */ -enum class ArtifactBinOp { +enum class ArtifactBinOp +{ eq, notEq, less, @@ -242,16 +243,17 @@ enum class ArtifactBinOp { /** * @brief Represents different types of binary expressions. */ -class ArtifactBinaryExpr : public ArtifactExpr { +class ArtifactBinaryExpr : public ArtifactExpr +{ public: ArtifactBinaryExpr(ArtifactBinOp op, std::shared_ptr left, - std::shared_ptr right) : - _op(op), _left(std::move(left)), _right(std::move(right)) {} - - void accept(IArtifactGenerator* g) const override { - g->visit(this); + std::shared_ptr right) + : _op(op), _left(std::move(left)), _right(std::move(right)) + { } + void accept(IArtifactGenerator *g) const override { g->visit(this); } + ArtifactBinOp getOp() const { return _op; } std::shared_ptr getLeft() const { return _left; } std::shared_ptr getRight() const { return _right; } @@ -265,15 +267,16 @@ private: /** * @brief Array index access */ -class ArtifactIndex : public ArtifactExpr { +class ArtifactIndex : public ArtifactExpr +{ public: ArtifactIndex(std::shared_ptr expr, std::shared_ptr ind) - : _expr(std::move(expr)), _ind(std::move(ind)) {} - - void accept(IArtifactGenerator* g) const override { - g->visit(this); + : _expr(std::move(expr)), _ind(std::move(ind)) + { } + void accept(IArtifactGenerator *g) const override { g->visit(this); } + std::shared_ptr getExpr() const { return _expr; } std::shared_ptr getInd() const { return _ind; } @@ -285,84 +288,80 @@ private: /** * @brief Just represents return from function statement. */ - class ArtifactRet : public ArtifactEntity { - public: - explicit ArtifactRet(std::shared_ptr expr) : _expr(std::move(expr)) {} +class ArtifactRet : public ArtifactEntity +{ +public: + explicit ArtifactRet(std::shared_ptr expr) : _expr(std::move(expr)) {} - void accept(IArtifactGenerator* g) const override { - g->visit(this); - } + void accept(IArtifactGenerator *g) const override { g->visit(this); } - std::shared_ptr expr() const { return _expr; } + std::shared_ptr expr() const { return _expr; } - private: - std::shared_ptr _expr; - }; +private: + std::shared_ptr _expr; +}; /** * @brief Just represents the break statement. */ -class ArtifactBreak : public ArtifactEntity { +class ArtifactBreak : public ArtifactEntity +{ public: - void accept(IArtifactGenerator* g) const override { - g->visit(this); - } + void accept(IArtifactGenerator *g) const override { g->visit(this); } }; /** * @brief Just represents the continue statement. */ -class ArtifactCont : public ArtifactEntity { +class ArtifactCont : public ArtifactEntity +{ public: - void accept(IArtifactGenerator* g) const override { - g->visit(this); - } + void accept(IArtifactGenerator *g) const override { g->visit(this); } }; /** * @brief Represents a variable. */ -class ArtifactVariable : public ArtifactNamed { +class ArtifactVariable : public ArtifactNamed +{ public: ArtifactVariable(std::string type_name, std::string var_name, std::list> dimensions = {}, std::list> initializers = {}) - : _typeName(std::move(type_name)), _dimensions(std::move(dimensions)), - _initializers(std::move(initializers)), ArtifactNamed(std::move(var_name)) {} - - void accept(IArtifactGenerator* g) const override { - g->visit(this); + : _typeName(std::move(type_name)), _dimensions(std::move(dimensions)), + _initializers(std::move(initializers)), ArtifactNamed(std::move(var_name)) + { } - const std::string& typeName() const { return _typeName; } - const std::list>& getDimensions() const { return _dimensions; }; - const std::list>& getInitializers() const { return _initializers; } + void accept(IArtifactGenerator *g) const override { g->visit(this); } + + const std::string &typeName() const { return _typeName; } + const std::list> &getDimensions() const { return _dimensions; }; + const std::list> &getInitializers() const { return _initializers; } std::shared_ptr use() { return std::make_shared(this); } private: std::string _typeName; - std::list> _dimensions;// If not empty, this is an array + std::list> _dimensions; // If not empty, this is an array std::list> _initializers; }; /** * @brief Represents a block of instructions. */ -class ArtifactBlock : public ArtifactEntity { +class ArtifactBlock : public ArtifactEntity +{ public: bool isBlock() const override { return true; } - void accept(IArtifactGenerator* g) const override { - g->visit(this); - } + void accept(IArtifactGenerator *g) const override { g->visit(this); } - void addStatement(const std::shared_ptr& statement) { + void addStatement(const std::shared_ptr &statement) + { _statements.push_back(statement); } - const std::list>& getStatements() const { - return _statements; - } + const std::list> &getStatements() const { return _statements; } /** * @brief Creates a new variable and place it to the block. @@ -372,10 +371,10 @@ public: * @param initializers - optional arguments of the object constructor. * @return - the newly created variable. */ - std::shared_ptr var( - const std::string& type_name, const std::string& var_name, - const std::list>& dimensions = {}, - const std::list>& initializers = {}); + std::shared_ptr + var(const std::string &type_name, const std::string &var_name, + const std::list> &dimensions = {}, + const std::list> &initializers = {}); /** * @brief Creates a function call. * @param func_name - the function name. @@ -384,11 +383,10 @@ public: * @param call_type - (for member functions only) call through: '.', '->', or '::'. * @return */ - std::shared_ptr call( - const std::string& func_name, - const std::list>& param_list, - std::shared_ptr call_on = nullptr, - ArtifactCallType call_type = ArtifactCallType::obj); + std::shared_ptr + call(const std::string &func_name, const std::list> ¶m_list, + std::shared_ptr call_on = nullptr, + ArtifactCallType call_type = ArtifactCallType::obj); /** * @brief Creates a return from function statement. * @param expr - value to return in generated code. @@ -465,24 +463,25 @@ private: /** * @brief Represents for loops. */ -class ArtifactForLoop : public ArtifactEntity { +class ArtifactForLoop : public ArtifactEntity +{ public: explicit ArtifactForLoop(std::shared_ptr init = nullptr, std::shared_ptr cond = nullptr, std::shared_ptr iter = nullptr) - : _init(std::move(init)), _cond(std::move(cond)), _iter(std::move(iter)) {} + : _init(std::move(init)), _cond(std::move(cond)), _iter(std::move(iter)) + { + } bool isBlock() const override { return true; } - void accept(IArtifactGenerator* g) const override { - g->visit(this); - } + void accept(IArtifactGenerator *g) const override { g->visit(this); } std::shared_ptr getInit() const { return _init; } std::shared_ptr getCond() const { return _cond; } std::shared_ptr getIter() const { return _iter; } - const ArtifactBlock* getBlock() const { return &_body; } - ArtifactBlock* getBlock() { return &_body; } + const ArtifactBlock *getBlock() const { return &_body; } + ArtifactBlock *getBlock() { return &_body; } private: std::shared_ptr _init; @@ -494,20 +493,19 @@ private: /** * @brief Represents if block. */ -class ArtifactIf : public ArtifactEntity { +class ArtifactIf : public ArtifactEntity +{ public: explicit ArtifactIf(std::shared_ptr cond) : _cond(std::move(cond)) {} bool isBlock() const override { return true; } - void accept(IArtifactGenerator* g) const override { - g->visit(this); - } + void accept(IArtifactGenerator *g) const override { g->visit(this); } std::shared_ptr getCond() const { return _cond; } - const ArtifactBlock* getBlock() const { return &_body; } - ArtifactBlock* getBlock() { return &_body; } - const ArtifactBlock* getElseBlock() const { return &_elseBody; } - ArtifactBlock* getElseBlock() { return &_elseBody; } + const ArtifactBlock *getBlock() const { return &_body; } + ArtifactBlock *getBlock() { return &_body; } + const ArtifactBlock *getElseBlock() const { return &_elseBody; } + ArtifactBlock *getElseBlock() { return &_elseBody; } private: std::shared_ptr _cond; @@ -518,7 +516,8 @@ private: /** * @brief Represents a function. */ -class ArtifactFunction : public ArtifactNamed { +class ArtifactFunction : public ArtifactNamed +{ public: /** * @brief Constructs a function object. @@ -526,19 +525,18 @@ public: * @param func_name - the function name. * @param params - the parameter list. */ - ArtifactFunction(std::string ret_type_name, const std::string& func_name, - std::list> params = {}) : - ArtifactNamed(func_name), _params(std::move(params)), - _retTypeName(std::move(ret_type_name)) {} - - void accept(IArtifactGenerator* g) const override { - g->visit(this); + ArtifactFunction(std::string ret_type_name, const std::string &func_name, + std::list> params = {}) + : ArtifactNamed(func_name), _params(std::move(params)), _retTypeName(std::move(ret_type_name)) + { } - const std::list>& getParameters() const { return _params; } - const std::string& getRetTypeName() const { return _retTypeName; } - const ArtifactBlock* getBlock() const { return &_body; } - ArtifactBlock* getBlock() { return &_body; } + void accept(IArtifactGenerator *g) const override { g->visit(this); } + + const std::list> &getParameters() const { return _params; } + const std::string &getRetTypeName() const { return _retTypeName; } + const ArtifactBlock *getBlock() const { return &_body; } + ArtifactBlock *getBlock() { return &_body; } private: std::list> _params; @@ -549,57 +547,59 @@ private: /** * @brief Basic class for both class member variables and memmber functions. */ -class ArtifactClassMember { +class ArtifactClassMember +{ public: - explicit ArtifactClassMember(const ArtifactClass* owner) : _owner(owner) {} + explicit ArtifactClassMember(const ArtifactClass *owner) : _owner(owner) {} - const ArtifactClass* owner() const { return _owner; } + const ArtifactClass *owner() const { return _owner; } protected: - const ArtifactClass* _owner; + const ArtifactClass *_owner; }; /** * @brief A class member variables. */ -class ArtifactClassVariable : public ArtifactClassMember, public ArtifactVariable { +class ArtifactClassVariable : public ArtifactClassMember, public ArtifactVariable +{ public: - ArtifactClassVariable(const ArtifactClass* owner, const std::string& type_name, - const std::string& var_name, - const std::list>& dimensions = {}, - const std::list>& initializers = {}) - : ArtifactClassMember(owner), ArtifactVariable(type_name, var_name, dimensions, initializers) {} - - void accept(IArtifactGenerator* g) const override { - g->visit(this); + ArtifactClassVariable(const ArtifactClass *owner, const std::string &type_name, + const std::string &var_name, + const std::list> &dimensions = {}, + const std::list> &initializers = {}) + : ArtifactClassMember(owner), ArtifactVariable(type_name, var_name, dimensions, initializers) + { } + + void accept(IArtifactGenerator *g) const override { g->visit(this); } }; /** * @brief A class for member functions. */ -class ArtifactClassFunction : public ArtifactClassMember, public ArtifactFunction { +class ArtifactClassFunction : public ArtifactClassMember, public ArtifactFunction +{ public: - ArtifactClassFunction(const ArtifactClass* owner, const std::string& ret_type_name, - const std::string& func_name, - const std::list>& params = {}) - : ArtifactClassMember(owner), ArtifactFunction(ret_type_name, func_name, params) {} - - void accept(IArtifactGenerator* g) const override { - g->visit(this); + ArtifactClassFunction(const ArtifactClass *owner, const std::string &ret_type_name, + const std::string &func_name, + const std::list> ¶ms = {}) + : ArtifactClassMember(owner), ArtifactFunction(ret_type_name, func_name, params) + { } + + void accept(IArtifactGenerator *g) const override { g->visit(this); } }; /** * @brief Represents a class. */ -class ArtifactClass : public ArtifactNamed { +class ArtifactClass : public ArtifactNamed +{ public: - explicit ArtifactClass(const std::string& class_name) : ArtifactNamed(class_name) {} + explicit ArtifactClass(const std::string &class_name) : ArtifactNamed(class_name) {} - void accept(IArtifactGenerator* g) const override { - g->visit(this); - } + void accept(IArtifactGenerator *g) const override { g->visit(this); } /** * @brief Creates a class member variable. @@ -611,17 +611,20 @@ public: * @param constructors * @return */ - std::shared_ptr var( - bool is_public, const std::string& type_name, - const std::string& var_name, - const std::list>& dimensions = {}, - const std::list>& initializers = {}) { - if (is_public) { + std::shared_ptr + var(bool is_public, const std::string &type_name, const std::string &var_name, + const std::list> &dimensions = {}, + const std::list> &initializers = {}) + { + if (is_public) + { auto var = std::make_shared(this, type_name, var_name, dimensions, initializers); _publicVariables.push_back(var); return var; - } else { + } + else + { auto var = std::make_shared(this, type_name, var_name, dimensions, initializers); _privateVariables.push_back(var); @@ -637,81 +640,84 @@ public: * @param params * @return */ - std::shared_ptr func( - bool is_public, - const std::string& ret_type_name, const std::string& func_name, - const std::list>& params = {}) { - if (is_public) { + std::shared_ptr + func(bool is_public, const std::string &ret_type_name, const std::string &func_name, + const std::list> ¶ms = {}) + { + if (is_public) + { auto func = std::make_shared(this, ret_type_name, func_name, params); _publicFunctions.push_back(func); return func; - } else { + } + else + { auto func = std::make_shared(this, ret_type_name, func_name, params); _privateFunctions.push_back(func); return func; } } - const std::list>& publicVariables() const { + const std::list> &publicVariables() const + { return _publicVariables; } - const std::list>& privateVariables() const { + const std::list> &privateVariables() const + { return _privateVariables; } - const std::list>& publicFunctions() const { + const std::list> &publicFunctions() const + { return _publicFunctions; } - const std::list>& privateFunctions() const { + const std::list> &privateFunctions() const + { return _privateFunctions; } - ArtifactBlock* getConstrBlock() { - return &_constrBlock; - } + ArtifactBlock *getConstrBlock() { return &_constrBlock; } - const ArtifactBlock* getConstrBlock() const { - return &_constrBlock; - } + const ArtifactBlock *getConstrBlock() const { return &_constrBlock; } private: - std::list> _publicVariables; - std::list> _privateVariables; - std::list> _publicFunctions; - std::list> _privateFunctions; - ArtifactBlock _constrBlock; + std::list> _publicVariables; + std::list> _privateVariables; + std::list> _publicFunctions; + std::list> _privateFunctions; + ArtifactBlock _constrBlock; }; /** * @brief Class representing a module in the ACL C++ soft backend. */ -class ArtifactModule { +class ArtifactModule +{ public: explicit ArtifactModule(std::string name) : _name(std::move(name)) {} - void accept(IArtifactGenerator* g) const { - g->visit(this); - } + void accept(IArtifactGenerator *g) const { g->visit(this); } - std::shared_ptr createClass(const std::string& name) { + std::shared_ptr createClass(const std::string &name) + { auto a_class = std::make_shared(name); _entities.emplace_back(a_class); return a_class; } - void addHeaderInclude(const std::string& name) { _headerIncludes.push_back(name); } - void addSourceInclude(const std::string& name) { _sourceIncludes.push_back(name); } - void addHeaderSysInclude(const std::string& name) { _headerSysIncludes.push_back(name); } - void addSourceSysInclude(const std::string& name) { _sourceSysIncludes.push_back(name); } + void addHeaderInclude(const std::string &name) { _headerIncludes.push_back(name); } + void addSourceInclude(const std::string &name) { _sourceIncludes.push_back(name); } + void addHeaderSysInclude(const std::string &name) { _headerSysIncludes.push_back(name); } + void addSourceSysInclude(const std::string &name) { _sourceSysIncludes.push_back(name); } - const std::string& name() const { return _name; } + const std::string &name() const { return _name; } const std::list> entities() const { return _entities; } - const std::list& headerIncludes() const { return _headerIncludes; } - const std::list& sourceIncludes() const { return _sourceIncludes; } - const std::list& headerSysIncludes() const { return _headerSysIncludes; } - const std::list& sourceSysIncludes() const { return _sourceSysIncludes; } + const std::list &headerIncludes() const { return _headerIncludes; } + const std::list &sourceIncludes() const { return _sourceIncludes; } + const std::list &headerSysIncludes() const { return _headerSysIncludes; } + const std::list &sourceSysIncludes() const { return _sourceSysIncludes; } private: std::string _name; @@ -725,13 +731,16 @@ private: /** * @brief Factory for some kinds of frequently used artifact DOM objects. */ -class ArtifactFactory { +class ArtifactFactory +{ public: - static std::shared_ptr id(const std::string& name) { + static std::shared_ptr id(const std::string &name) + { return std::make_shared(name); } - static std::shared_ptr lit(const std::string& name) { + static std::shared_ptr lit(const std::string &name) + { return std::make_shared(name); } @@ -744,10 +753,11 @@ public: * @param constructors - optional arguments of the object constructor, if instantiating a class. * @return - the newly created variable. */ - static std::shared_ptr var( - const std::string& type_name, - const std::string& var_name, const std::list>& dimensions = {}, - const std::list>& initializers = {}) { + static std::shared_ptr + var(const std::string &type_name, const std::string &var_name, + const std::list> &dimensions = {}, + const std::list> &initializers = {}) + { return std::make_shared(type_name, var_name, dimensions, initializers); } @@ -756,7 +766,8 @@ public: * @param ref * @return */ - static std::shared_ptr ref(std::shared_ptr ref) { + static std::shared_ptr ref(std::shared_ptr ref) + { return std::make_shared(ref); } @@ -765,7 +776,8 @@ public: * @param ref * @return */ - static std::shared_ptr deref(std::shared_ptr ref) { + static std::shared_ptr deref(std::shared_ptr ref) + { return std::make_shared(ref); } @@ -777,12 +789,12 @@ public: * @param call_type - (for member functions only) call through: '.', '->', or '::'. * @return */ - static std::shared_ptr call( - const std::string& func_name, - const std::list>& param_list, - std::shared_ptr on = nullptr, - ArtifactCallType call_type = ArtifactCallType::obj) { - return std::make_shared(func_name, param_list, on, call_type); + static std::shared_ptr + call(const std::string &func_name, const std::list> ¶m_list, + std::shared_ptr on = nullptr, + ArtifactCallType call_type = ArtifactCallType::obj) + { + return std::make_shared(func_name, param_list, on, call_type); } /** @@ -791,8 +803,8 @@ public: * @param expr * @return */ - static std::shared_ptr un(ArtifactUnOp op, - std::shared_ptr expr) { + static std::shared_ptr un(ArtifactUnOp op, std::shared_ptr expr) + { return std::make_shared(op, expr); } @@ -803,9 +815,9 @@ public: * @param right * @return */ - static std::shared_ptr bin( - ArtifactBinOp op, - std::shared_ptr left, std::shared_ptr right) { + static std::shared_ptr + bin(ArtifactBinOp op, std::shared_ptr left, std::shared_ptr right) + { return std::make_shared(op, left, right); } @@ -816,7 +828,8 @@ public: * @return */ static std::shared_ptr ind(std::shared_ptr expr, - std::shared_ptr ind) { + std::shared_ptr ind) + { return std::make_shared(expr, ind); } @@ -825,7 +838,8 @@ public: * @param expr * @return */ - static std::shared_ptr heapNew(std::shared_ptr expr) { + static std::shared_ptr heapNew(std::shared_ptr expr) + { return std::make_shared(ArtifactUnOp::heapNew, expr); } @@ -834,7 +848,8 @@ public: * @param expr * @return */ - static std::shared_ptr heapFree(std::shared_ptr expr) { + static std::shared_ptr heapFree(std::shared_ptr expr) + { return std::make_shared(ArtifactUnOp::heapFree, expr); } }; diff --git a/compiler/nnc/passes/acl_soft_backend/IArtifactGenerator.h b/compiler/nnc/passes/acl_soft_backend/IArtifactGenerator.h index 30bd09e..02ccbb6 100644 --- a/compiler/nnc/passes/acl_soft_backend/IArtifactGenerator.h +++ b/compiler/nnc/passes/acl_soft_backend/IArtifactGenerator.h @@ -48,30 +48,31 @@ class ArtifactClassFunction; /** * @brief The interface of the artifact source code producer. */ -class IArtifactGenerator { +class IArtifactGenerator +{ public: virtual ~IArtifactGenerator() = default; - virtual void visit(const ArtifactLiteral* node) = 0; - virtual void visit(const ArtifactId* node) = 0; - virtual void visit(const ArtifactRef* node) = 0; - virtual void visit(const ArtifactDeref* node) = 0; - virtual void visit(const ArtifactVariable* node) = 0; - virtual void visit(const ArtifactFunctionCall* node) = 0; - virtual void visit(const ArtifactUnaryExpr* node) = 0; - virtual void visit(const ArtifactBinaryExpr* node) = 0; - virtual void visit(const ArtifactIndex* node) = 0; - virtual void visit(const ArtifactRet* node) = 0; - virtual void visit(const ArtifactBreak* node) = 0; - virtual void visit(const ArtifactCont* node) = 0; - virtual void visit(const ArtifactBlock* node) = 0; - virtual void visit(const ArtifactForLoop* node) = 0; - virtual void visit(const ArtifactIf* node) = 0; - virtual void visit(const ArtifactFunction* node) = 0; - virtual void visit(const ArtifactClass* node) = 0; - virtual void visit(const ArtifactClassVariable* node) = 0; - virtual void visit(const ArtifactClassFunction* node) = 0; - virtual void visit(const ArtifactModule* node) = 0; + virtual void visit(const ArtifactLiteral *node) = 0; + virtual void visit(const ArtifactId *node) = 0; + virtual void visit(const ArtifactRef *node) = 0; + virtual void visit(const ArtifactDeref *node) = 0; + virtual void visit(const ArtifactVariable *node) = 0; + virtual void visit(const ArtifactFunctionCall *node) = 0; + virtual void visit(const ArtifactUnaryExpr *node) = 0; + virtual void visit(const ArtifactBinaryExpr *node) = 0; + virtual void visit(const ArtifactIndex *node) = 0; + virtual void visit(const ArtifactRet *node) = 0; + virtual void visit(const ArtifactBreak *node) = 0; + virtual void visit(const ArtifactCont *node) = 0; + virtual void visit(const ArtifactBlock *node) = 0; + virtual void visit(const ArtifactForLoop *node) = 0; + virtual void visit(const ArtifactIf *node) = 0; + virtual void visit(const ArtifactFunction *node) = 0; + virtual void visit(const ArtifactClass *node) = 0; + virtual void visit(const ArtifactClassVariable *node) = 0; + virtual void visit(const ArtifactClassFunction *node) = 0; + virtual void visit(const ArtifactModule *node) = 0; }; } // namespace nnc diff --git a/compiler/nnc/passes/common_frontend/NNImporter.cpp b/compiler/nnc/passes/common_frontend/NNImporter.cpp index 7aea496..d0f1635 100644 --- a/compiler/nnc/passes/common_frontend/NNImporter.cpp +++ b/compiler/nnc/passes/common_frontend/NNImporter.cpp @@ -5,40 +5,49 @@ #include "passes/common_frontend/NNImporter.h" #ifdef NNC_FRONTEND_TFLITE_ENABLED -# include "tflite_importer_pass.h" +#include "tflite_importer_pass.h" #endif // NNC_FRONTEND_TFLITE_ENABLED #ifdef NNC_FRONTEND_CAFFE_ENABLED -# include "caffe_importer_pass.h" +#include "caffe_importer_pass.h" #endif // NNC_FRONTEND_CAFFE_ENABLED #ifdef NNC_FRONTEND_CAFFE2_ENABLED -# include "caffe2_importer_pass.h" +#include "caffe2_importer_pass.h" #endif // NNC_FRONTEND_CAFFE2_ENABLED #ifdef NNC_FRONTEND_ONNX_ENABLED -# include "ONNXImporterPass.h" +#include "ONNXImporterPass.h" #endif // NNC_FRONTEND_ONNX_ENABLED -namespace nnc { +namespace nnc +{ -std::unique_ptr NNImporter::createNNImporter() { +std::unique_ptr NNImporter::createNNImporter() +{ std::unique_ptr importer(nullptr); - if (cli::caffeFrontend) { + if (cli::caffeFrontend) + { #ifdef NNC_FRONTEND_CAFFE_ENABLED importer.reset(new CaffeImporterPass(cli::inputFile.getRawValue())); #endif // NNC_FRONTEND_CAFFE_ENABLED - } else if (cli::caffe2Frontend) { + } + else if (cli::caffe2Frontend) + { #ifdef NNC_FRONTEND_CAFFE2_ENABLED // FIXME: caffe2 input shapes are not provided by model and must be set from cli // current 'inputShapes' could provide only one shape, while model could has several inputs importer.reset(new Caffe2ImporterPass(cli::inputFile.getRawValue(), cli::initNet.getRawValue(), - {cli::inputShapes.getRawValue()})); + {cli::inputShapes.getRawValue()})); #endif // NNC_FRONTEND_CAFFE2_ENABLED - } else if (cli::onnxFrontend) { + } + else if (cli::onnxFrontend) + { #ifdef NNC_FRONTEND_ONNX_ENABLED importer.reset(new ONNXImporterPass(cli::inputFile.getRawValue())); #endif // NNC_FRONTEND_ONNX_ENABLED - } else if (cli::tflFrontend) { + } + else if (cli::tflFrontend) + { #ifdef NNC_FRONTEND_TFLITE_ENABLED importer.reset(new TfliteImporterPass(cli::inputFile.getRawValue())); #endif // NNC_FRONTEND_TFLITE_ENABLED diff --git a/compiler/nnc/passes/dot_dumper/DumperPass.cpp b/compiler/nnc/passes/dot_dumper/DumperPass.cpp index 83789f7..196490d 100644 --- a/compiler/nnc/passes/dot_dumper/DumperPass.cpp +++ b/compiler/nnc/passes/dot_dumper/DumperPass.cpp @@ -20,19 +20,20 @@ #include - -namespace nnc { +namespace nnc +{ using namespace mir; int DumperPass::_counter = 0; -PassData DumperPass::run(PassData data) { - auto g = static_cast(data); +PassData DumperPass::run(PassData data) +{ + auto g = static_cast(data); assert(g); IrDotDumper dotDumper; g->accept(&dotDumper); std::ofstream f_out; - f_out.open(std::to_string(_counter)+ "_"+ _file_name + ".dot"); + f_out.open(std::to_string(_counter) + "_" + _file_name + ".dot"); dotDumper.writeDot(f_out); f_out.close(); diff --git a/compiler/nnc/passes/interpreter/Interpreter.cpp b/compiler/nnc/passes/interpreter/Interpreter.cpp index d477282..f0ec990 100644 --- a/compiler/nnc/passes/interpreter/Interpreter.cpp +++ b/compiler/nnc/passes/interpreter/Interpreter.cpp @@ -45,33 +45,40 @@ #include #include -namespace nnc { +namespace nnc +{ using namespace mir; std::vector> -NNInterpreter::getInputTensors(const Operation& op) { +NNInterpreter::getInputTensors(const Operation &op) +{ std::vector> tensors; - for (const auto& input : op.getInputs()) { - const auto* producer = input.getProducer(); + for (const auto &input : op.getInputs()) + { + const auto *producer = input.getProducer(); tensors.emplace_back(_opResults.at(producer->getNode()).at(producer->getIndex())); } return tensors; } -void NNInterpreter::setOutputTensors(const Operation& op, std::vector&& outputs) { +void NNInterpreter::setOutputTensors(const Operation &op, std::vector &&outputs) +{ _opResults.emplace(&op, std::move(outputs)); } -void NNInterpreter::setInput(const std::string &name, const TensorVariant& data) { +void NNInterpreter::setInput(const std::string &name, const TensorVariant &data) +{ _inputTensors.emplace(name, data); } -TensorVariant NNInterpreter::getResult(const Operation::Output* tensor) { +TensorVariant NNInterpreter::getResult(const Operation::Output *tensor) +{ return _opResults.at(tensor->getNode()).at(tensor->getIndex()); } -void NNInterpreter::visit(ops::InputOp& op) { +void NNInterpreter::visit(ops::InputOp &op) +{ auto it = _inputTensors.find(op.getName()); if (it == _inputTensors.end()) throw std::runtime_error("Can't find data for node \"" + op.getName() + @@ -79,102 +86,117 @@ void NNInterpreter::visit(ops::InputOp& op) { setOutputTensors(op, {it->second}); } -void NNInterpreter::visit(ops::ConstantOp& op) { +void NNInterpreter::visit(ops::ConstantOp &op) +{ assert(_inputTensors.find(op.getName()) == _inputTensors.end()); setOutputTensors(op, {op.getValue()}); } -void NNInterpreter::visit(ops::ConcatOp& op) { +void NNInterpreter::visit(ops::ConcatOp &op) +{ auto inputs = getInputTensors(op); auto outputs = Concat(inputs, op.getOutputShape(0), op.getAxis())(); setOutputTensors(op, std::move(outputs)); } -void NNInterpreter::visit(ops::Conv2DOp& op) { +void NNInterpreter::visit(ops::Conv2DOp &op) +{ auto inputs = getInputTensors(op); auto outputs = Conv2D(inputs[0], inputs[1], op)(); setOutputTensors(op, std::move(outputs)); } -void NNInterpreter::visit(ops::ReshapeOp& op) { +void NNInterpreter::visit(ops::ReshapeOp &op) +{ auto inputs = getInputTensors(op); auto outputs = Reshape(inputs[0], op.getOutputShape(0))(); setOutputTensors(op, std::move(outputs)); } -void NNInterpreter::visit(ops::ReluOp& op) { +void NNInterpreter::visit(ops::ReluOp &op) +{ auto inputs = getInputTensors(op); Tensor input(inputs[0]); auto outputs = Fill(op.getOutputShape(0), - [&input](const Index& id) { return std::max(input.at(id), 0.0f); })(); + [&input](const Index &id) { return std::max(input.at(id), 0.0f); })(); setOutputTensors(op, std::move(outputs)); } -void NNInterpreter::visit(ops::SigmoidOp& op) { +void NNInterpreter::visit(ops::SigmoidOp &op) +{ auto inputs = getInputTensors(op); Tensor input(inputs[0]); - auto outputs = Fill(op.getOutputShape(0), [&input](const Index& id) { + auto outputs = Fill(op.getOutputShape(0), [&input](const Index &id) { return 1.f / (1.f + std::exp(-input.at(id))); })(); setOutputTensors(op, std::move(outputs)); } -void NNInterpreter::visit(ops::SoftmaxOp& op) { +void NNInterpreter::visit(ops::SoftmaxOp &op) +{ auto inputs = getInputTensors(op); auto outputs = Softmax(inputs[0], op.getAxis())(); setOutputTensors(op, std::move(outputs)); } -void NNInterpreter::visit(ops::PoolOp& op) { +void NNInterpreter::visit(ops::PoolOp &op) +{ auto inputs = getInputTensors(op); auto outputs = Pool(inputs[0], op)(); setOutputTensors(op, std::move(outputs)); } -void NNInterpreter::visit(ops::FullyConnectedOp& op) { +void NNInterpreter::visit(ops::FullyConnectedOp &op) +{ auto inputs = getInputTensors(op); auto outputs = FullyConnected(inputs[0], inputs[1], op)(); setOutputTensors(op, std::move(outputs)); } -void NNInterpreter::visit(ops::GemmOp& op) { +void NNInterpreter::visit(ops::GemmOp &op) +{ auto inputs = getInputTensors(op); auto outputs = Gemm(inputs[0], inputs[1], inputs[2], op)(); setOutputTensors(op, std::move(outputs)); } -void NNInterpreter::visit(ops::CappedReluOp& op) { +void NNInterpreter::visit(ops::CappedReluOp &op) +{ auto inputs = getInputTensors(op); Tensor input(inputs[0]); - auto outputs = Fill(op.getOutputShape(0), [&input, &op](const Index& id) { + auto outputs = Fill(op.getOutputShape(0), [&input, &op](const Index &id) { return std::min(std::max(input.at(id), 0.0f), op.getCap()); })(); setOutputTensors(op, std::move(outputs)); } -void NNInterpreter::visit(ops::DepthwiseConv2DOp& op) { +void NNInterpreter::visit(ops::DepthwiseConv2DOp &op) +{ auto inputs = getInputTensors(op); auto outputs = DepthwiseConv2D(inputs[0], inputs[1], op)(); setOutputTensors(op, std::move(outputs)); } -void NNInterpreter::visit(ops::BatchNormOp& op) { +void NNInterpreter::visit(ops::BatchNormOp &op) +{ auto inputs = getInputTensors(op); auto outputs = BatchNorm(inputs[0], op)(); setOutputTensors(op, std::move(outputs)); } -void NNInterpreter::visit(ops::SliceOp& op) { +void NNInterpreter::visit(ops::SliceOp &op) +{ auto inputs = getInputTensors(op); auto input = Tensor(inputs[0]); - auto outputs = Fill(op.getOutputShape(0), [&input, &op](const Index& id) { + auto outputs = Fill(op.getOutputShape(0), [&input, &op](const Index &id) { Index idx = nnc::shift(id, op.getStarts()); return input.at(idx); })(); setOutputTensors(op, std::move(outputs)); } -void NNInterpreter::visit(ops::DropoutOp& op) { +void NNInterpreter::visit(ops::DropoutOp &op) +{ auto inputs = getInputTensors(op); TensorVariant input(inputs[0]); // TODO implement this @@ -182,25 +204,27 @@ void NNInterpreter::visit(ops::DropoutOp& op) { setOutputTensors(op, std::move(outputs)); } -void NNInterpreter::visit(ops::TanhOp& op) { +void NNInterpreter::visit(ops::TanhOp &op) +{ auto inputs = getInputTensors(op); Tensor input(inputs[0]); - auto outputs = Fill(op.getOutputShape(0), [&input](const Index& id) { - return std::tanh(input.at(id)); - })(); + auto outputs = Fill(op.getOutputShape(0), + [&input](const Index &id) { return std::tanh(input.at(id)); })(); setOutputTensors(op, std::move(outputs)); } -void NNInterpreter::visit(ops::DeConv2DOp& op) { +void NNInterpreter::visit(ops::DeConv2DOp &op) +{ auto inputs = getInputTensors(op); auto outputs = DeConv2D(inputs[0], inputs[1], op)(); setOutputTensors(op, std::move(outputs)); } -void NNInterpreter::visit(ops::EluOp& op) { +void NNInterpreter::visit(ops::EluOp &op) +{ auto inputs = getInputTensors(op); Tensor input(inputs[0]); - auto outputs = Fill(op.getOutputShape(0), [&input, &op](const Index& id) { + auto outputs = Fill(op.getOutputShape(0), [&input, &op](const Index &id) { if (input.at(id) >= 0) return input.at(id); else @@ -209,74 +233,83 @@ void NNInterpreter::visit(ops::EluOp& op) { setOutputTensors(op, std::move(outputs)); } -void NNInterpreter::visit(ops::SqueezeOp& op) { +void NNInterpreter::visit(ops::SqueezeOp &op) +{ auto inputs = getInputTensors(op); // Squeeze is just a special case of reshape. auto outputs = Reshape(inputs[0], op.getOutputShape(0))(); setOutputTensors(op, std::move(outputs)); } -void NNInterpreter::visit(ops::PadOp& op) { +void NNInterpreter::visit(ops::PadOp &op) +{ auto inputs = getInputTensors(op); auto outputs = Pad(inputs[0], op)(); setOutputTensors(op, std::move(outputs)); } -void NNInterpreter::visit(ops::SqrtOp& op) { +void NNInterpreter::visit(ops::SqrtOp &op) +{ auto inputs = getInputTensors(op); Tensor input(inputs[0]); - auto outputs = Fill(op.getOutputShape(0), [&input](const Index id) { - return sqrt(input.at(id)); - })(); + auto outputs = + Fill(op.getOutputShape(0), [&input](const Index id) { return sqrt(input.at(id)); })(); setOutputTensors(op, std::move(outputs)); } -void NNInterpreter::visit(ops::ResizeOp& op) { +void NNInterpreter::visit(ops::ResizeOp &op) +{ auto inputs = getInputTensors(op); Tensor input(inputs[0]); assert(op.getMode() == ops::ResizeOp::ResizeMethod::nearestNeighbor); auto scales = op.getScales(); - auto outputs = Fill(op.getOutputShape(0), [&scales, &input](const Index& id) { + auto outputs = Fill(op.getOutputShape(0), [&scales, &input](const Index &id) { Index in_idx; in_idx.resize(4); - for (int i = 0; i < input.getShape().rank(); i++) { - in_idx.at(i) = static_cast (floorf(id.at(i) / scales[i])); + for (int i = 0; i < input.getShape().rank(); i++) + { + in_idx.at(i) = static_cast(floorf(id.at(i) / scales[i])); } return input.at(in_idx); })(); setOutputTensors(op, std::move(outputs)); } -void NNInterpreter::visit(ops::ReduceOp& op) { +void NNInterpreter::visit(ops::ReduceOp &op) +{ auto inputs = getInputTensors(op); auto outputs = Reduce(inputs[0], op)(); setOutputTensors(op, std::move(outputs)); } -void NNInterpreter::visit(ops::TransposeOp& op) { +void NNInterpreter::visit(ops::TransposeOp &op) +{ auto inputs = getInputTensors(op); auto outputs = Transpose(inputs[0], op)(); setOutputTensors(op, std::move(outputs)); } -void NNInterpreter::visit(ops::GatherOp& op) { +void NNInterpreter::visit(ops::GatherOp &op) +{ auto inputs = getInputTensors(op); auto outputs = Gather(inputs[0], inputs[1], op)(); setOutputTensors(op, std::move(outputs)); } -void NNInterpreter::visit(ops::LeakyReluOp& op) { +void NNInterpreter::visit(ops::LeakyReluOp &op) +{ auto inputs = getInputTensors(op); float alpha = op.getAlpha(); Tensor input(inputs[0]); - auto outputs = Fill(op.getOutputShape(0), [&input, alpha](const Index& id) { + auto outputs = Fill(op.getOutputShape(0), [&input, alpha](const Index &id) { float val = input.at(id); return val > 0.0f ? val : val * alpha; })(); setOutputTensors(op, std::move(outputs)); } -void NNInterpreter::visit(ops::OutputOp& /*op*/) { +void NNInterpreter::visit(ops::OutputOp & /*op*/) +{ // No-op. } diff --git a/compiler/nnc/passes/interpreter/interpreter_pass.cpp b/compiler/nnc/passes/interpreter/interpreter_pass.cpp index ad9f8c4..fe18399 100644 --- a/compiler/nnc/passes/interpreter/interpreter_pass.cpp +++ b/compiler/nnc/passes/interpreter/interpreter_pass.cpp @@ -25,7 +25,7 @@ #ifdef NNC_HDF5_SUPPORTED #include -#endif // NNC_HDF5_SUPPORTED +#endif // NNC_HDF5_SUPPORTED #include "mir/Shape.h" @@ -41,8 +41,8 @@ #include "mir/ShapeRange.h" #include "mir/Tensor.h" - -namespace nnc { +namespace nnc +{ using namespace mir; @@ -54,15 +54,16 @@ using namespace mir; * @param tensor_name - name, by wich tensor will be saved * @param destination - path to file, in which tensor will be saved */ -static void writeTensorToHDF5File(const TensorVariant& tensor, - std::string tensor_name, - const std::string& destination) { +static void writeTensorToHDF5File(const TensorVariant &tensor, std::string tensor_name, + const std::string &destination) +{ // Prepare shape, rank, dims, numElems - auto& shape = tensor.getShape(); + auto &shape = tensor.getShape(); const int32_t rank = shape.rank(); hsize_t dims[rank]; - for (int32_t axis = 0; axis < rank; ++axis) { + for (int32_t axis = 0; axis < rank; ++axis) + { dims[axis] = static_cast(shape.dim(axis)); } @@ -72,7 +73,7 @@ static void writeTensorToHDF5File(const TensorVariant& tensor, ShapeRange out_range(shape); Tensor tensor_accessor(tensor); - for (auto& out_idx : out_range) + for (auto &out_idx : out_range) values.push_back(tensor_accessor.at(out_idx)); // Backslashes are not allowed in tensor names @@ -86,10 +87,11 @@ static void writeTensorToHDF5File(const TensorVariant& tensor, dataset.write(values.data(), H5::PredType::NATIVE_FLOAT); } -#endif // NNC_HDF5_SUPPORTED +#endif // NNC_HDF5_SUPPORTED -static TensorVariant readTensorFromFile(const std::string& filename, DataType data_type, - const Shape& shape) { +static TensorVariant readTensorFromFile(const std::string &filename, DataType data_type, + const Shape &shape) +{ assert(data_type == DataType::FLOAT32); std::size_t input_data_size = shape.numElements() * sizeof(float); @@ -105,8 +107,8 @@ static TensorVariant readTensorFromFile(const std::string& filename, DataType da if (static_cast(file_size) != input_data_size) throw PassException("File \"" + filename + "\" has incorrect size: " + - std::to_string(file_size) + - "(expected: " + std::to_string(input_data_size) + ")."); + std::to_string(file_size) + "(expected: " + + std::to_string(input_data_size) + ")."); std::unique_ptr data(new char[input_data_size]); stream.read(data.get(), input_data_size); @@ -116,13 +118,15 @@ static TensorVariant readTensorFromFile(const std::string& filename, DataType da return TensorVariant(data_type, shape, data.get()); } -PassData InterpreterPass::run(PassData data) { - auto g = static_cast(data); +PassData InterpreterPass::run(PassData data) +{ + auto g = static_cast(data); assert(g); NNInterpreter interpreter; - for (const auto* input_op : g->getInputs()) { + for (const auto *input_op : g->getInputs()) + { std::string tensor_name = input_op->getName(); std::replace(tensor_name.begin(), tensor_name.end(), '/', '_'); std::string filename = cli::interInputDataDir + "/" + tensor_name + ".dat"; @@ -132,15 +136,16 @@ PassData InterpreterPass::run(PassData data) { g->accept(&interpreter); - for (const auto* output_op : g->getOutputs()) { - const auto& tensor = interpreter.getResult(output_op->getInput(0)->getProducer()); + for (const auto *output_op : g->getOutputs()) + { + const auto &tensor = interpreter.getResult(output_op->getInput(0)->getProducer()); #ifdef NNC_HDF5_SUPPORTED writeTensorToHDF5File(tensor, output_op->getName(), cli::artifactDir); #else - std::cout << "Result <" << output_op->getName() - << "> wasn't saved, due to lack of HDF5" << std::endl; -#endif // NNC_HDF5_SUPPORTED + std::cout << "Result <" << output_op->getName() << "> wasn't saved, due to lack of HDF5" + << std::endl; +#endif // NNC_HDF5_SUPPORTED } return nullptr; diff --git a/compiler/nnc/passes/interpreter/ops/BatchNorm.h b/compiler/nnc/passes/interpreter/ops/BatchNorm.h index 87a2305..a410e22 100644 --- a/compiler/nnc/passes/interpreter/ops/BatchNorm.h +++ b/compiler/nnc/passes/interpreter/ops/BatchNorm.h @@ -30,15 +30,17 @@ namespace nnc * @note Simply copies input to output * @tparam T type of data in input tensor */ -template -class BatchNorm : public OperationImpl +template class BatchNorm : public OperationImpl { public: /** * @param in input data * @param op batch normalization operation description */ - explicit BatchNorm(const mir::TensorVariant& input, const mir::ops::BatchNormOp& op) : _input(input), _op(op) {} + explicit BatchNorm(const mir::TensorVariant &input, const mir::ops::BatchNormOp &op) + : _input(input), _op(op) + { + } /** * @brief computes operation aplication result @@ -46,15 +48,13 @@ public: */ std::vector operator()() override { - //For now BatchNorm just copies input to output - return Fill(_input.getShape(), [this](const mir::Index& idx) { - return _input.at(idx); - })(); + // For now BatchNorm just copies input to output + return Fill(_input.getShape(), [this](const mir::Index &idx) { return _input.at(idx); })(); } private: const mir::Tensor _input; - const mir::ops::BatchNormOp& _op; + const mir::ops::BatchNormOp &_op; }; } // namespace nnc diff --git a/compiler/nnc/passes/interpreter/ops/Concat.h b/compiler/nnc/passes/interpreter/ops/Concat.h index 24151cd..31632ec 100644 --- a/compiler/nnc/passes/interpreter/ops/Concat.h +++ b/compiler/nnc/passes/interpreter/ops/Concat.h @@ -19,30 +19,34 @@ #include "Fill.h" -namespace nnc { +namespace nnc +{ -template -class Concat : public Fill { +template class Concat : public Fill +{ public: - Concat(const std::vector>& inputs, - const mir::Shape& outputShape, - int32_t axis) - : Fill(outputShape, getSingleFunction(inputs, axis)) {} + Concat(const std::vector> &inputs, + const mir::Shape &outputShape, int32_t axis) + : Fill(outputShape, getSingleFunction(inputs, axis)) + { + } private: - const std::function - getSingleFunction(const std::vector>& inputs, - int32_t axis) { + const std::function + getSingleFunction(const std::vector> &inputs, + int32_t axis) + { std::vector> inputAccessors; inputAccessors.reserve(inputs.size()); - for (auto& in : inputs) + for (auto &in : inputs) inputAccessors.emplace_back(in); - return std::function([inputAccessors, axis](const mir::Index& id) -> T { + return std::function([inputAccessors, axis](const mir::Index &id) -> T { unsigned int mi = 0; int32_t along_axis = id.at(axis); - while (along_axis >= inputAccessors.at(mi).getShape().dim(axis)) { + while (along_axis >= inputAccessors.at(mi).getShape().dim(axis)) + { along_axis -= inputAccessors[mi].getShape().dim(axis); mi++; } diff --git a/compiler/nnc/passes/interpreter/ops/Conv2D.cpp b/compiler/nnc/passes/interpreter/ops/Conv2D.cpp index 18a1157..c7f10d0 100644 --- a/compiler/nnc/passes/interpreter/ops/Conv2D.cpp +++ b/compiler/nnc/passes/interpreter/ops/Conv2D.cpp @@ -18,7 +18,8 @@ #include "mir/ShapeRange.h" #include "mir/TensorUtil.h" -namespace nnc { +namespace nnc +{ using namespace mir; @@ -26,12 +27,13 @@ using namespace mir; // Assuming input is in NHWC format with batch omitted( [in_height, in_width, in_channels] ) // Kernel is in [filter_height, filter_width, in_channels, out_channels] // Refer to https://www.tensorflow.org/api_docs/python/tf/nn/conv2d for info -std::vector Conv2D::operator()() { - const Shape& in_shape = _input.getShape(); - const Shape& kernel_shape = _kernel.getShape(); - const Shape& out_shape = _op.getOutputShape(0); - const Shape& strides = _op.getStrides(); - const std::vector& pads = _op.getPaddingBefore(); +std::vector Conv2D::operator()() +{ + const Shape &in_shape = _input.getShape(); + const Shape &kernel_shape = _kernel.getShape(); + const Shape &out_shape = _op.getOutputShape(0); + const Shape &strides = _op.getStrides(); + const std::vector &pads = _op.getPaddingBefore(); assert(in_shape.rank() == 4); assert(kernel_shape.rank() == 4); @@ -53,20 +55,24 @@ std::vector Conv2D::operator()() { Index in_index; in_index.resize(4); - for (const auto& out_index : out_range) { + for (const auto &out_index : out_range) + { auto out_region = res_accessor.getRegion(out_index); assert(out_region.size() == num_kernels); - for (const auto& kernel_index : kernel_range) { + for (const auto &kernel_index : kernel_range) + { in_index.at(0) = out_index.at(0); for (int i = 0; i < 2; ++i) in_index.at(1 + i) = out_index.at(1 + i) * strides.dim(i) + kernel_index.at(i) - pads[i]; in_index.at(3) = kernel_index.at(2); - if (in_range.contains(in_index)) { + if (in_range.contains(in_index)) + { auto kernel_region = kernel.getRegion(kernel_index); assert(kernel_region.size() == num_kernels); float in_val = _input.at(in_index); - for (int32_t kernel_i = 0; kernel_i < num_kernels; ++kernel_i) { + for (int32_t kernel_i = 0; kernel_i < num_kernels; ++kernel_i) + { out_region.base()[kernel_i] += in_val * kernel_region.base()[kernel_i]; } } @@ -76,10 +82,9 @@ std::vector Conv2D::operator()() { return {res}; } -Conv2D::Conv2D(const TensorVariant& input, - const TensorVariant& kernel, - const ops::Conv2DOp& op) - : _input(input), _kernel(transposeTensor<1, 2, 3, 0>(kernel)), _op(op) { +Conv2D::Conv2D(const TensorVariant &input, const TensorVariant &kernel, const ops::Conv2DOp &op) + : _input(input), _kernel(transposeTensor<1, 2, 3, 0>(kernel)), _op(op) +{ } } // namespace nnc diff --git a/compiler/nnc/passes/interpreter/ops/Conv2D.h b/compiler/nnc/passes/interpreter/ops/Conv2D.h index a7e465b..760cfee 100644 --- a/compiler/nnc/passes/interpreter/ops/Conv2D.h +++ b/compiler/nnc/passes/interpreter/ops/Conv2D.h @@ -21,23 +21,23 @@ #include "mir/ops/Conv2DOp.h" #include "mir/Tensor.h" -namespace nnc { +namespace nnc +{ -class Conv2D : public OperationImpl { +class Conv2D : public OperationImpl +{ public: - Conv2D(const mir::TensorVariant& input, - const mir::TensorVariant& kernel, - const mir::ops::Conv2DOp& op); + Conv2D(const mir::TensorVariant &input, const mir::TensorVariant &kernel, + const mir::ops::Conv2DOp &op); std::vector operator()() override; private: const mir::Tensor _input; mir::TensorVariant _kernel; - const mir::ops::Conv2DOp& _op; + const mir::ops::Conv2DOp &_op; }; } // namespace nnc #endif //_NNC_CORE_BACKEND_INTERPRETER_CONV2D_IMPL - diff --git a/compiler/nnc/passes/interpreter/ops/DeConv2D.cpp b/compiler/nnc/passes/interpreter/ops/DeConv2D.cpp index 8f5d31a..31f743a 100644 --- a/compiler/nnc/passes/interpreter/ops/DeConv2D.cpp +++ b/compiler/nnc/passes/interpreter/ops/DeConv2D.cpp @@ -23,13 +23,15 @@ #include "common.h" #include -namespace nnc { +namespace nnc +{ using namespace mir; using namespace mir::ops; -std::vector nnc::DeConv2D::operator()() { - const auto& strides = _op.getStrides(); +std::vector nnc::DeConv2D::operator()() +{ + const auto &strides = _op.getStrides(); Shape out_shape = _op.getOutputShape(0); auto res = allocate_tensor(out_shape); Tensor res_accesor(res); @@ -41,7 +43,7 @@ std::vector nnc::DeConv2D::operator()() { Shape in_shape = _input.getShape(); ShapeRange in_range(in_shape); - auto tr_kernel = transposeTensor<0,1,3,2>(_kernel); + auto tr_kernel = transposeTensor<0, 1, 3, 2>(_kernel); Tensor kernel(tr_kernel); Shape k_shape = kernel.getShape(); @@ -55,14 +57,17 @@ std::vector nnc::DeConv2D::operator()() { Index kernel_idx; kernel_idx.resize(k_shape.rank()); - for (auto& out_idx : out_range) { + for (auto &out_idx : out_range) + { auto out_region = res_accesor.getRegion(out_idx); assert(out_region.size() == num_kernels); - for (auto& kernel_idx_r : kernel_range) { + for (auto &kernel_idx_r : kernel_range) + { // rotate kernel 180 deg around last axis // by index transform - for (int32_t d = 0; d < 2; ++d) { + for (int32_t d = 0; d < 2; ++d) + { kernel_idx.at(d) = kernel.getShape().dim(d) - kernel_idx_r.at(d) - 1; } kernel_idx.at(2) = kernel_idx_r.at(2); @@ -71,28 +76,33 @@ std::vector nnc::DeConv2D::operator()() { // flag that keeps info on whether the current input element is from input // or is from dilation by stride bool is_from_input = true; - for (int32_t d = 1; d < input_idx.rank() - 1; ++d) { + for (int32_t d = 1; d < input_idx.rank() - 1; ++d) + { const auto num = (out_idx.at(d) + pads.at(d - 1) - kernel_idx.at(d - 1)); - auto stride = strides.dim(d - 1 ); + auto stride = strides.dim(d - 1); const auto div_res = num / stride; - const auto rem = num - div_res*stride; + const auto rem = num - div_res * stride; is_from_input = is_from_input && rem == 0; - if (rem != 0) break; + if (rem != 0) + break; input_idx.at(d) = div_res; } - if (is_from_input) { + if (is_from_input) + { // batch is same as output's input_idx.at(0) = out_idx.at(0); // channel index - same as kernel's input_idx.at(3) = kernel_idx.at(2); - if (in_range.contains(input_idx)) { + if (in_range.contains(input_idx)) + { auto kernel_region = kernel.getRegion(kernel_idx); assert(kernel_region.size() == num_kernels); auto in = _input.at(input_idx); - for (int32_t kernel_index = 0; kernel_index < num_kernels; kernel_index++) { + for (int32_t kernel_index = 0; kernel_index < num_kernels; kernel_index++) + { out_region.base()[kernel_index] += in * kernel_region.base()[kernel_index]; } } @@ -102,13 +112,14 @@ std::vector nnc::DeConv2D::operator()() { return {res}; } -DeConv2D::DeConv2D(const TensorVariant& input, const TensorVariant& kernel, const DeConv2DOp& op) - : _input(input), _kernel(kernel), _op(op) { +DeConv2D::DeConv2D(const TensorVariant &input, const TensorVariant &kernel, const DeConv2DOp &op) + : _input(input), _kernel(kernel), _op(op) +{ // Input shape: [N, Hi, Wi, Ci] // Kernel shape: [Hk, Wk, Co, Ci] assert(_op.getInputShape(0).rank() == 4); - const auto& input_shape = _input.getShape(); - const auto& kernel_shape = _kernel.getShape(); + const auto &input_shape = _input.getShape(); + const auto &kernel_shape = _kernel.getShape(); assert(input_shape.rank() == 4); assert(kernel_shape.rank() == 4); assert(kernel_shape.dim(3) == input_shape.dim(3)); diff --git a/compiler/nnc/passes/interpreter/ops/DeConv2D.h b/compiler/nnc/passes/interpreter/ops/DeConv2D.h index ad10beb..89f9dfc 100644 --- a/compiler/nnc/passes/interpreter/ops/DeConv2D.h +++ b/compiler/nnc/passes/interpreter/ops/DeConv2D.h @@ -21,7 +21,8 @@ #include "mir/ops/Deconv2DOp.h" #include "mir/Tensor.h" -namespace nnc { +namespace nnc +{ /** * @brief Transposed convolution (or Deconvolution) @@ -32,21 +33,20 @@ namespace nnc { * hence all the indexing can be deducted by expressing the input index * of Conv in terms of it's output index. */ -class DeConv2D : public OperationImpl { +class DeConv2D : public OperationImpl +{ public: - DeConv2D(const mir::TensorVariant& input, - const mir::TensorVariant& kernel, - const mir::ops::DeConv2DOp& op); + DeConv2D(const mir::TensorVariant &input, const mir::TensorVariant &kernel, + const mir::ops::DeConv2DOp &op); std::vector operator()() override; private: const mir::Tensor _input; const mir::TensorVariant _kernel; - const mir::ops::DeConv2DOp& _op; + const mir::ops::DeConv2DOp &_op; }; } // namespace nnc - #endif //_NNC_CORE_BACKEND_INTERPRETER_DECONV2D_IMPL_ diff --git a/compiler/nnc/passes/interpreter/ops/DepthwiseConv2D.cpp b/compiler/nnc/passes/interpreter/ops/DepthwiseConv2D.cpp index ad9c037..0fc1e37 100644 --- a/compiler/nnc/passes/interpreter/ops/DepthwiseConv2D.cpp +++ b/compiler/nnc/passes/interpreter/ops/DepthwiseConv2D.cpp @@ -17,16 +17,18 @@ #include "DepthwiseConv2D.h" #include "mir/ShapeRange.h" -namespace nnc { +namespace nnc +{ using namespace mir; -std::vector DepthwiseConv2D::operator()() { - const Shape& in_shape = _op.getInputShape(0); - const Shape& kernel_shape = _op.getInputShape(1); - const Shape& out_shape = _op.getOutputShape(0); - const Shape& strides = _op.getStrides(); - const std::vector& pads = _op.getPaddingBefore(); +std::vector DepthwiseConv2D::operator()() +{ + const Shape &in_shape = _op.getInputShape(0); + const Shape &kernel_shape = _op.getInputShape(1); + const Shape &out_shape = _op.getOutputShape(0); + const Shape &strides = _op.getStrides(); + const std::vector &pads = _op.getPaddingBefore(); assert(in_shape.rank() == 4); assert(kernel_shape.rank() == 4); @@ -47,15 +49,18 @@ std::vector DepthwiseConv2D::operator()() { Index in_index; in_index.resize(4); - for (const auto& out_index : out_range) { + for (const auto &out_index : out_range) + { Index out_index_k = out_index; - for (const auto& kernel_index : kernel_range) { + for (const auto &kernel_index : kernel_range) + { in_index.at(0) = out_index.at(0); for (int i = 0; i < 2; ++i) in_index.at(1 + i) = out_index.at(1 + i) * strides.dim(i) + kernel_index.at(i) - pads[i]; in_index.at(3) = kernel_index.at(2); - if (in_range.contains(in_index)) { + if (in_range.contains(in_index)) + { out_index_k.at(3) = kernel_index.at(2) * channel_multiplier + kernel_index.at(3); res_accessor.at(out_index_k) += _input.at(in_index) * _kernel.at(kernel_index); } @@ -65,10 +70,10 @@ std::vector DepthwiseConv2D::operator()() { return {res}; } -DepthwiseConv2D::DepthwiseConv2D(const TensorVariant& input, - const TensorVariant& kernel, - const ops::DepthwiseConv2DOp& op) - : _input(input), _kernel(kernel), _op(op) { +DepthwiseConv2D::DepthwiseConv2D(const TensorVariant &input, const TensorVariant &kernel, + const ops::DepthwiseConv2DOp &op) + : _input(input), _kernel(kernel), _op(op) +{ } } // namespace nnc diff --git a/compiler/nnc/passes/interpreter/ops/DepthwiseConv2D.h b/compiler/nnc/passes/interpreter/ops/DepthwiseConv2D.h index 0c643d9..ab6c65a 100644 --- a/compiler/nnc/passes/interpreter/ops/DepthwiseConv2D.h +++ b/compiler/nnc/passes/interpreter/ops/DepthwiseConv2D.h @@ -21,20 +21,21 @@ #include "mir/ops/DepthwiseConv2DOp.h" #include "mir/Tensor.h" -namespace nnc { +namespace nnc +{ -class DepthwiseConv2D : public OperationImpl { +class DepthwiseConv2D : public OperationImpl +{ public: - DepthwiseConv2D(const mir::TensorVariant& input, - const mir::TensorVariant& kernel, - const mir::ops::DepthwiseConv2DOp& op); + DepthwiseConv2D(const mir::TensorVariant &input, const mir::TensorVariant &kernel, + const mir::ops::DepthwiseConv2DOp &op); std::vector operator()() override; private: const mir::Tensor _input; const mir::Tensor _kernel; - const mir::ops::DepthwiseConv2DOp& _op; + const mir::ops::DepthwiseConv2DOp &_op; }; } // namespace nnc diff --git a/compiler/nnc/passes/interpreter/ops/Dropout.h b/compiler/nnc/passes/interpreter/ops/Dropout.h index dd4f7a1..9f6c40f 100644 --- a/compiler/nnc/passes/interpreter/ops/Dropout.h +++ b/compiler/nnc/passes/interpreter/ops/Dropout.h @@ -30,14 +30,17 @@ namespace nnc * @note Simply copies input to output * @tparam T type of data in input tensor */ -template -class Dropout : public OperationImpl { +template class Dropout : public OperationImpl +{ public: /** * @param in input data * @param op dropout operation description */ - explicit Dropout(const mir::TensorVariant& in, const mir::ops::DropoutOp& op) : _input(in), _op(op) {} + explicit Dropout(const mir::TensorVariant &in, const mir::ops::DropoutOp &op) + : _input(in), _op(op) + { + } /** * @brief computes operation aplication result @@ -47,16 +50,13 @@ public: private: const mir::Tensor _input; - const mir::ops::DropoutOp& _op; + const mir::ops::DropoutOp &_op; }; -template -std::vector Dropout::operator()() +template std::vector Dropout::operator()() { - //For now dropout just copies input to output - return Fill(_input.getShape(), [this](const mir::Index& idx) { - return _input.at(idx); - })(); + // For now dropout just copies input to output + return Fill(_input.getShape(), [this](const mir::Index &idx) { return _input.at(idx); })(); } } // namespace nnc diff --git a/compiler/nnc/passes/interpreter/ops/Fill.h b/compiler/nnc/passes/interpreter/ops/Fill.h index 669024e..dfdd44b 100644 --- a/compiler/nnc/passes/interpreter/ops/Fill.h +++ b/compiler/nnc/passes/interpreter/ops/Fill.h @@ -22,19 +22,24 @@ #include "mir/Tensor.h" #include -namespace nnc { +namespace nnc +{ -template -class Fill : public OperationImpl { +template class Fill : public OperationImpl +{ public: - Fill(const mir::Shape& shape, std::function f) : - _shape(shape), _fval(std::move(f)) {} + Fill(const mir::Shape &shape, std::function f) + : _shape(shape), _fval(std::move(f)) + { + } - std::vector operator()() override { + std::vector operator()() override + { auto res = OperationImpl::allocate_tensor(_shape); mir::Tensor res_accessor(res); - for (const auto& index : mir::ShapeRange(_shape)) { + for (const auto &index : mir::ShapeRange(_shape)) + { res_accessor.at(index) = _fval(index); } @@ -43,7 +48,7 @@ public: private: const mir::Shape _shape; - const std::function _fval; + const std::function _fval; }; } // namespace nnc diff --git a/compiler/nnc/passes/interpreter/ops/FullyConnected.cpp b/compiler/nnc/passes/interpreter/ops/FullyConnected.cpp index 64a4d7a..36b6460 100644 --- a/compiler/nnc/passes/interpreter/ops/FullyConnected.cpp +++ b/compiler/nnc/passes/interpreter/ops/FullyConnected.cpp @@ -16,21 +16,24 @@ #include "FullyConnected.h" -namespace nnc { +namespace nnc +{ -FullyConnected::FullyConnected(const mir::TensorVariant& input, - const mir::TensorVariant& weights, - const mir::ops::FullyConnectedOp& _op) - : _op(_op), _input(input), _weights(weights) {} +FullyConnected::FullyConnected(const mir::TensorVariant &input, const mir::TensorVariant &weights, + const mir::ops::FullyConnectedOp &_op) + : _op(_op), _input(input), _weights(weights) +{ +} -std::vector FullyConnected::operator()() { +std::vector FullyConnected::operator()() +{ mir::TensorVariant res = OperationImpl::allocate_tensor(_op.getOutputShape(0)); mir::Tensor accessor(res); - const mir::Shape& in_shape = _input.getShape(); + const mir::Shape &in_shape = _input.getShape(); int32_t in_rank = in_shape.rank(); - const mir::Shape& w_shape = _weights.getShape(); + const mir::Shape &w_shape = _weights.getShape(); int32_t w_rank = w_shape.rank(); assert(in_shape.dim(in_rank - 1) == w_shape.dim(w_rank - 2)); @@ -40,12 +43,14 @@ std::vector FullyConnected::operator()() { int32_t len = w_shape.dim(w_rank - 2); - for (auto& out_index : out_range) { + for (auto &out_index : out_range) + { mir::Index t_index = out_index; - float& output_element = accessor.at(out_index); + float &output_element = accessor.at(out_index); int32_t col = t_index.at(w_rank - 1); int32_t row = t_index.at(w_rank - 2); - for (int32_t i = 0; i < len; ++i) { + for (int32_t i = 0; i < len; ++i) + { t_index.at(w_rank - 1) = i; float in = _input.at(t_index); t_index.at(w_rank - 1) = col; @@ -59,4 +64,4 @@ std::vector FullyConnected::operator()() { return {res}; } -} // namespace nnc +} // namespace nnc diff --git a/compiler/nnc/passes/interpreter/ops/FullyConnected.h b/compiler/nnc/passes/interpreter/ops/FullyConnected.h index fc4cf1c..941170b 100644 --- a/compiler/nnc/passes/interpreter/ops/FullyConnected.h +++ b/compiler/nnc/passes/interpreter/ops/FullyConnected.h @@ -22,18 +22,19 @@ #include "mir/Tensor.h" #include "mir/ShapeRange.h" -namespace nnc { +namespace nnc +{ -class FullyConnected : public OperationImpl { +class FullyConnected : public OperationImpl +{ public: - FullyConnected(const mir::TensorVariant& input, - const mir::TensorVariant& weights, - const mir::ops::FullyConnectedOp& _op); + FullyConnected(const mir::TensorVariant &input, const mir::TensorVariant &weights, + const mir::ops::FullyConnectedOp &_op); std::vector operator()() override; private: - const mir::ops::FullyConnectedOp& _op; + const mir::ops::FullyConnectedOp &_op; const mir::Tensor _input; const mir::Tensor _weights; }; diff --git a/compiler/nnc/passes/interpreter/ops/Gather.cpp b/compiler/nnc/passes/interpreter/ops/Gather.cpp index 9fea54d..dca6f11 100644 --- a/compiler/nnc/passes/interpreter/ops/Gather.cpp +++ b/compiler/nnc/passes/interpreter/ops/Gather.cpp @@ -16,18 +16,20 @@ #include "Gather.h" -namespace nnc { +namespace nnc +{ using namespace mir; -Gather::Gather(const TensorVariant& data, - const TensorVariant& indices, - const ops::GatherOp& op) - : _data(data), _indices(indices), _op(op) {} +Gather::Gather(const TensorVariant &data, const TensorVariant &indices, const ops::GatherOp &op) + : _data(data), _indices(indices), _op(op) +{ +} -std::vector Gather::operator()() { - const auto& data_shape = _data.getShape(); - const auto& indices_shape = _indices.getShape(); +std::vector Gather::operator()() +{ + const auto &data_shape = _data.getShape(); + const auto &indices_shape = _indices.getShape(); auto res = allocate_tensor(_op.getOutputShape(0)); Tensor data(_data); Tensor indices(_indices); @@ -48,11 +50,14 @@ std::vector Gather::operator()() { for (int32_t i = axis + 1; i < data_shape.rank(); ++i) inner_size *= data_shape.dim(i); - for (int32_t outer = 0; outer < outer_size; ++outer) { - for (int32_t i = 0; i < num_indices; ++i) { + for (int32_t outer = 0; outer < outer_size; ++outer) + { + for (int32_t i = 0; i < num_indices; ++i) + { auto index = static_cast(indices.atOffset(i)); assert(index >= 0 && index < axis_size); - for (int32_t inner = 0; inner < inner_size; inner++) { + for (int32_t inner = 0; inner < inner_size; inner++) + { output.atOffset((outer * num_indices + i) * inner_size + inner) = data.atOffset((outer * axis_size + index) * inner_size + inner); } diff --git a/compiler/nnc/passes/interpreter/ops/Gather.h b/compiler/nnc/passes/interpreter/ops/Gather.h index 5e872cc..22fe077 100644 --- a/compiler/nnc/passes/interpreter/ops/Gather.h +++ b/compiler/nnc/passes/interpreter/ops/Gather.h @@ -21,22 +21,23 @@ #include "mir/ops/GatherOp.h" #include "mir/Tensor.h" -namespace nnc { +namespace nnc +{ -class Gather : public OperationImpl { +class Gather : public OperationImpl +{ public: - Gather(const mir::TensorVariant& data, - const mir::TensorVariant& indices, - const mir::ops::GatherOp& op); + Gather(const mir::TensorVariant &data, const mir::TensorVariant &indices, + const mir::ops::GatherOp &op); std::vector operator()() override; private: const mir::Tensor _data; const mir::Tensor _indices; - const mir::ops::GatherOp& _op; + const mir::ops::GatherOp &_op; }; -} // namespace nnc +} // namespace nnc #endif //_NNC_CORE_BACKEND_INTERPRETER_GATHER_ diff --git a/compiler/nnc/passes/interpreter/ops/Gemm.h b/compiler/nnc/passes/interpreter/ops/Gemm.h index 83be0d0..ffde2a3 100644 --- a/compiler/nnc/passes/interpreter/ops/Gemm.h +++ b/compiler/nnc/passes/interpreter/ops/Gemm.h @@ -23,15 +23,19 @@ #include "mir/TensorVariant.h" #include "mir/ShapeRange.h" -namespace nnc { -template -class Gemm : public OperationImpl { +namespace nnc +{ +template class Gemm : public OperationImpl +{ public: - Gemm(const mir::TensorVariant& a, const mir::TensorVariant& b, - const mir::TensorVariant& c, mir::ops::GemmOp& op) : - _op(op), _tensor_a(a), _tensor_b(b), _tensor_c(c) {} + Gemm(const mir::TensorVariant &a, const mir::TensorVariant &b, const mir::TensorVariant &c, + mir::ops::GemmOp &op) + : _op(op), _tensor_a(a), _tensor_b(b), _tensor_c(c) + { + } - std::vector operator()() override { + std::vector operator()() override + { mir::TensorVariant res = OperationImpl::allocate_tensor(_op.getOutputShape(0)); mir::Tensor accessor(res); mir::ShapeRange out_range(res.getShape()); @@ -39,7 +43,7 @@ public: auto b_shape = _tensor_b.getShape(); int32_t b_rank = b_shape.rank(); - auto& in_shape = _tensor_a.getShape(); + auto &in_shape = _tensor_a.getShape(); int32_t in_rank = in_shape.rank(); assert(in_shape.dim(in_rank - 1) == b_shape.dim(b_rank - 2)); (void)in_rank; @@ -48,17 +52,19 @@ public: auto len = b_shape.dim(b_rank - 2); int32_t row; int32_t col; - for (auto &out_idx : out_range) { + for (auto &out_idx : out_range) + { mir::Index t_idx = out_idx; - T& output_element = accessor.at(out_idx); + T &output_element = accessor.at(out_idx); col = t_idx.at(-1); row = t_idx.at(-2); - for (int32_t i = 0; i < len; ++i) { + for (int32_t i = 0; i < len; ++i) + { t_idx.at(-1) = i; - T& in = _tensor_a.at(t_idx); + T &in = _tensor_a.at(t_idx); t_idx.at(-1) = col; t_idx.at(-2) = i; - T& w = _tensor_b.at(t_idx); + T &w = _tensor_b.at(t_idx); t_idx.at(-2) = row; output_element += w * in; } @@ -68,19 +74,19 @@ public: // We'd like to broadcast Tensor C to the output shape assert(_op.getOutputShape(0).rank() == 2); assert((_op.getOutputShape(0).rank() == _op.getInputShape(2).rank()) || - ((_op.getInputShape(2).rank() == 1) && - (_op.getOutputShape(0).dim(0) == 1))); + ((_op.getInputShape(2).rank() == 1) && (_op.getOutputShape(0).dim(0) == 1))); - auto t = mir::TensorVariant (_tensor_c, _op.getOutputShape(0)); + auto t = mir::TensorVariant(_tensor_c, _op.getOutputShape(0)); mir::Tensor tensor_c(t); - for (auto idx : mir::ShapeRange(_op.getOutputShape(0))) { + for (auto idx : mir::ShapeRange(_op.getOutputShape(0))) + { accessor.at(idx) += tensor_c.at(idx); } return {res}; } private: - mir::ops::GemmOp& _op; + mir::ops::GemmOp &_op; mir::Tensor _tensor_a; mir::Tensor _tensor_b; mir::TensorVariant _tensor_c; diff --git a/compiler/nnc/passes/interpreter/ops/OperationImpl.h b/compiler/nnc/passes/interpreter/ops/OperationImpl.h index 9476f22..6dbdf8e 100644 --- a/compiler/nnc/passes/interpreter/ops/OperationImpl.h +++ b/compiler/nnc/passes/interpreter/ops/OperationImpl.h @@ -21,15 +21,17 @@ #include "mir/Shape.h" #include -namespace nnc { +namespace nnc +{ -template -class OperationImpl { +template class OperationImpl +{ public: virtual std::vector operator()() = 0; protected: - mir::TensorVariant allocate_tensor(const mir::Shape& shape) { + mir::TensorVariant allocate_tensor(const mir::Shape &shape) + { // Use hardcoded DataType for now, since theres no support for operations on types other than // floats std::vector zeros(static_cast(shape.numElements()), 0.0f); diff --git a/compiler/nnc/passes/interpreter/ops/Pad.cpp b/compiler/nnc/passes/interpreter/ops/Pad.cpp index ec4c13a..4699ebc 100644 --- a/compiler/nnc/passes/interpreter/ops/Pad.cpp +++ b/compiler/nnc/passes/interpreter/ops/Pad.cpp @@ -18,11 +18,13 @@ #include "Pad.h" -namespace nnc { +namespace nnc +{ using namespace mir; -std::vector Pad::operator()() { +std::vector Pad::operator()() +{ auto result = allocate_tensor(_op.getOutputShape(0)); Tensor result_accessor(result); @@ -35,22 +37,30 @@ std::vector Pad::operator()() { temp_index.resize(rank); bool index_on_padding(false); - for (const Index& ind : out_range) { + for (const Index &ind : out_range) + { index_on_padding = false; - for (int32_t i = 0; i < rank; i++) { + for (int32_t i = 0; i < rank; i++) + { // index on input values if (ind.at(i) >= _op.getPaddingForDim(i).first && - ind.at(i) < out_shape.dim(i) - _op.getPaddingForDim(i).second) { + ind.at(i) < out_shape.dim(i) - _op.getPaddingForDim(i).second) + { temp_index.at(i) = ind.at(i) - _op.getPaddingForDim(i).first; - } else { // not in input + } + else + { // not in input index_on_padding = true; break; } } - if (index_on_padding) { + if (index_on_padding) + { result_accessor.at(ind) = _op.getScalar().get(); - } else { + } + else + { result_accessor.at(ind) = _input.at(temp_index); } } diff --git a/compiler/nnc/passes/interpreter/ops/Pad.h b/compiler/nnc/passes/interpreter/ops/Pad.h index 00d5313..1cc75f9 100644 --- a/compiler/nnc/passes/interpreter/ops/Pad.h +++ b/compiler/nnc/passes/interpreter/ops/Pad.h @@ -21,7 +21,8 @@ #include "mir/ops/PadOp.h" #include "mir/Tensor.h" -namespace nnc { +namespace nnc +{ /** * @brief Implements PadOp for interpreter backend * @@ -29,14 +30,15 @@ namespace nnc { * you specify. For each dimension of input add values * before and after of contents. */ -class Pad : public OperationImpl { +class Pad : public OperationImpl +{ public: /** * @param input The Input tensor * @param op The Pad operation object */ - Pad(const mir::TensorVariant& input, const mir::ops::PadOp& op) - : _input(input), _op(op) { + Pad(const mir::TensorVariant &input, const mir::ops::PadOp &op) : _input(input), _op(op) + { assert(_input.getShape().rank() == _op.getNumDim()); } @@ -48,7 +50,7 @@ public: private: const mir::Tensor _input; - const mir::ops::PadOp& _op; + const mir::ops::PadOp &_op; }; } // namespace nnc diff --git a/compiler/nnc/passes/interpreter/ops/Pool.cpp b/compiler/nnc/passes/interpreter/ops/Pool.cpp index 0443ee0..a940cfb 100644 --- a/compiler/nnc/passes/interpreter/ops/Pool.cpp +++ b/compiler/nnc/passes/interpreter/ops/Pool.cpp @@ -72,33 +72,39 @@ std::vector Pool::operator()() { float out = initialValue; size_t avgDenominator = 0; - for (auto& kIdx : ShapeRange(window_shape)) + for (auto &kIdx : ShapeRange(window_shape)) { translate(inIdx, outIdx, kIdx, strides, pads); float in = 0.0f; - if(inRange.contains(inIdx)) { + if (inRange.contains(inIdx)) + { avgDenominator++; in = _input.at(inIdx); - } else { - switch(_op.getBorderType()) { - case PoolOp::BorderType::ZEROFILLED: { - //Elements outside input range are zero + } + else + { + switch (_op.getBorderType()) + { + case PoolOp::BorderType::ZEROFILLED: + { + // Elements outside input range are zero avgDenominator++; in = 0.0f; break; } - case PoolOp::BorderType::EMPTY: { - //Skip all elements outside input range + case PoolOp::BorderType::EMPTY: + { + // Skip all elements outside input range continue; } - default: { + default: + { assert(false && "Invalid border type for pooling"); } } } out = poolingFunc(out, in); - } if (_op.getPoolingType() == PoolOp::PoolingType::AVG) { @@ -114,14 +120,14 @@ float Pool::poolingFunc(float prev, float val) { switch (_op.getPoolingType()) { - case PoolOp::PoolingType::MAX: - return (val > prev) ? val : prev; - case PoolOp::PoolingType::AVG: - return prev + val; - case PoolOp::PoolingType::MIN: - return (val < prev) ? val : prev; - default: - assert(false && "Unsupported pooling type"); + case PoolOp::PoolingType::MAX: + return (val > prev) ? val : prev; + case PoolOp::PoolingType::AVG: + return prev + val; + case PoolOp::PoolingType::MIN: + return (val < prev) ? val : prev; + default: + assert(false && "Unsupported pooling type"); } // This should not happen // Should throw, but it is too expensive diff --git a/compiler/nnc/passes/interpreter/ops/Pool.h b/compiler/nnc/passes/interpreter/ops/Pool.h index e2216ac..3ab79c5 100644 --- a/compiler/nnc/passes/interpreter/ops/Pool.h +++ b/compiler/nnc/passes/interpreter/ops/Pool.h @@ -35,7 +35,7 @@ public: float poolingFunc(float prev, float val); private: - const mir::ops::PoolOp&_op; + const mir::ops::PoolOp &_op; const mir::Tensor _input; }; diff --git a/compiler/nnc/passes/interpreter/ops/Reduce.h b/compiler/nnc/passes/interpreter/ops/Reduce.h index 3383066..4a72cd2 100644 --- a/compiler/nnc/passes/interpreter/ops/Reduce.h +++ b/compiler/nnc/passes/interpreter/ops/Reduce.h @@ -22,18 +22,19 @@ #include "mir/Tensor.h" #include "mir/ShapeRange.h" -namespace nnc { +namespace nnc +{ -template -class Reduce : public OperationImpl { +template class Reduce : public OperationImpl +{ public: - Reduce(const mir::TensorVariant& input, const mir::ops::ReduceOp& op) - : _input(input), _op(op) {} + Reduce(const mir::TensorVariant &input, const mir::ops::ReduceOp &op) : _input(input), _op(op) {} - std::vector operator()() override { - const auto& input_shape = _op.getInputShape(0); - const auto& output_shape = _op.getOutputShape(0); - const auto& reduction_dims = _op.getReductionDims(); + std::vector operator()() override + { + const auto &input_shape = _op.getInputShape(0); + const auto &output_shape = _op.getOutputShape(0); + const auto &reduction_dims = _op.getReductionDims(); const bool keep_dims = _op.getKeepDims(); assert(_op.getFuncType() == mir::ops::ReduceOp::FuncType::mean); @@ -45,19 +46,26 @@ public: // This mask contains `true` for axis that should be reduced. For example, if we want to reduce // axes 1 and 3 with total number of axes of 4, the mask will be [false, true, false, true]. std::vector reduce_axis_mask(input_shape.rank(), false); - for (auto axis : reduction_dims) { + for (auto axis : reduction_dims) + { reduce_axis_mask[axis] = true; } mir::Index out_index; out_index.resize(output_shape.rank()); - for (const mir::Index& in_index : mir::ShapeRange(input_shape)) { + for (const mir::Index &in_index : mir::ShapeRange(input_shape)) + { int32_t out_index_dim = 0; - for (int32_t d = 0; d < input_shape.rank(); ++d) { - if (keep_dims) { + for (int32_t d = 0; d < input_shape.rank(); ++d) + { + if (keep_dims) + { out_index.at(out_index_dim++) = reduce_axis_mask[d] ? 0 : in_index.at(d); - } else { - if (!reduce_axis_mask[d]) { + } + else + { + if (!reduce_axis_mask[d]) + { out_index.at(out_index_dim++) = in_index.at(d); } } @@ -67,7 +75,8 @@ public: const int32_t reduction_factor = input_shape.numElements() / output_shape.numElements(); - for (const auto& index : mir::ShapeRange(output_shape)) { + for (const auto &index : mir::ShapeRange(output_shape)) + { res_accessor.at(index) /= reduction_factor; } @@ -76,7 +85,7 @@ public: private: const mir::Tensor _input; - const mir::ops::ReduceOp& _op; + const mir::ops::ReduceOp &_op; }; } // namespace nnc diff --git a/compiler/nnc/passes/interpreter/ops/Reshape.h b/compiler/nnc/passes/interpreter/ops/Reshape.h index f2371a4..1979f5c 100644 --- a/compiler/nnc/passes/interpreter/ops/Reshape.h +++ b/compiler/nnc/passes/interpreter/ops/Reshape.h @@ -22,31 +22,34 @@ #include "OperationImpl.h" #include "Fill.h" -namespace nnc { +namespace nnc +{ -template -class Reshape : public OperationImpl { +template class Reshape : public OperationImpl +{ public: - Reshape(const mir::TensorVariant& input, const mir::Shape& output_shape) - : _input(input), - _output_shape(output_shape) { + Reshape(const mir::TensorVariant &input, const mir::Shape &output_shape) + : _input(input), _output_shape(output_shape) + { assert(input.getShape().numElements() == _output_shape.numElements()); } - std::vector operator()() override { + std::vector operator()() override + { mir::ShapeRange inRange(_input.getShape()); auto inIter = inRange.begin(); auto out = OperationImpl::allocate_tensor(_output_shape); // Shapes element count compared in Reshape ctor - return Fill(_output_shape, [this, &inIter](const mir::Index&) -> T { return _input.at(*inIter++); })(); + return Fill(_output_shape, + [this, &inIter](const mir::Index &) -> T { return _input.at(*inIter++); })(); } private: mir::Tensor _input; - const mir::Shape& _output_shape; + const mir::Shape &_output_shape; }; } // namespace nnc diff --git a/compiler/nnc/passes/interpreter/ops/Softmax.h b/compiler/nnc/passes/interpreter/ops/Softmax.h index 81713ce..50916c9 100644 --- a/compiler/nnc/passes/interpreter/ops/Softmax.h +++ b/compiler/nnc/passes/interpreter/ops/Softmax.h @@ -22,15 +22,16 @@ #include "mir/Tensor.h" #include -namespace nnc { +namespace nnc +{ -template -class Softmax : public OperationImpl { +template class Softmax : public OperationImpl +{ public: - Softmax(const mir::TensorVariant& input, int32_t axis) - : _input(input), _axis(axis) {} + Softmax(const mir::TensorVariant &input, int32_t axis) : _input(input), _axis(axis) {} - std::vector operator()() override { + std::vector operator()() override + { mir::Shape expsum_shape = _input.getShape(); expsum_shape.dim(_axis) = 1; @@ -40,18 +41,21 @@ public: mir::Tensor expsum_accessor(expsum); mir::Tensor res_accessor(res); - for (const auto& out_idx : mir::ShapeRange(expsum_shape)) { + for (const auto &out_idx : mir::ShapeRange(expsum_shape)) + { T element = T(); mir::Index in_idx = out_idx; int32_t end = _input.getShape().dim(_axis); - for (int32_t i = 0; i < end; ++i) { + for (int32_t i = 0; i < end; ++i) + { in_idx.at(_axis) = i; element += std::exp(input_accessor.at(in_idx)); } expsum_accessor.at(out_idx) = element; } - for (const auto& out_idx : mir::ShapeRange(_input.getShape())) { + for (const auto &out_idx : mir::ShapeRange(_input.getShape())) + { mir::Index expsum_idx = out_idx; expsum_idx.at(_axis) = 0; res_accessor.at(out_idx) = diff --git a/compiler/nnc/passes/interpreter/ops/Transpose.cpp b/compiler/nnc/passes/interpreter/ops/Transpose.cpp index 66e161d..7cb264d 100644 --- a/compiler/nnc/passes/interpreter/ops/Transpose.cpp +++ b/compiler/nnc/passes/interpreter/ops/Transpose.cpp @@ -18,26 +18,31 @@ #include "mir/Tensor.h" #include "mir/ShapeRange.h" -namespace nnc { +namespace nnc +{ using namespace mir; -Transpose::Transpose(const mir::TensorVariant& input, - const mir::ops::TransposeOp& op) : _op(op), _input(input) {} +Transpose::Transpose(const mir::TensorVariant &input, const mir::ops::TransposeOp &op) + : _op(op), _input(input) +{ +} -std::vector Transpose::operator()() { +std::vector Transpose::operator()() +{ auto res = allocate_tensor(_op.getOutputShape(0)); Tensor res_accessor(res); - auto& input_shape = _op.getInputShape(0); - auto& axis_order = _op.getAxisOrder(); + auto &input_shape = _op.getInputShape(0); + auto &axis_order = _op.getAxisOrder(); std::size_t num_axes = axis_order.size(); ShapeRange in_range(input_shape); Index out_index; out_index.resize(input_shape.rank()); - for (auto& in_index : in_range) { + for (auto &in_index : in_range) + { for (std::size_t i = 0; i < num_axes; ++i) out_index.at(static_cast(i)) = in_index.at(static_cast(axis_order.at(i))); res_accessor.at(out_index) = _input.at(in_index); @@ -46,4 +51,4 @@ std::vector Transpose::operator()() { return {res}; } -} // namespace nnc +} // namespace nnc diff --git a/compiler/nnc/passes/interpreter/ops/Transpose.h b/compiler/nnc/passes/interpreter/ops/Transpose.h index d89b36e..5266c2b 100644 --- a/compiler/nnc/passes/interpreter/ops/Transpose.h +++ b/compiler/nnc/passes/interpreter/ops/Transpose.h @@ -21,19 +21,21 @@ #include "mir/ops/TransposeOp.h" #include "mir/Tensor.h" -namespace nnc { +namespace nnc +{ -class Transpose : public OperationImpl { +class Transpose : public OperationImpl +{ public: std::vector operator()() override; - Transpose(const mir::TensorVariant& input, const mir::ops::TransposeOp& op); + Transpose(const mir::TensorVariant &input, const mir::ops::TransposeOp &op); private: - const mir::ops::TransposeOp& _op; + const mir::ops::TransposeOp &_op; const mir::Tensor _input; }; -} // namespace nnc +} // namespace nnc #endif //_NNC_CORE_BACKEND_INTERPRETER_TRANSPOSE_ diff --git a/compiler/nnc/passes/interpreter/ops/common.cpp b/compiler/nnc/passes/interpreter/ops/common.cpp index 1c615ca..109ea5f 100644 --- a/compiler/nnc/passes/interpreter/ops/common.cpp +++ b/compiler/nnc/passes/interpreter/ops/common.cpp @@ -34,10 +34,12 @@ void translate(Index &translatedIndex, const Index &sourceIndex, const Index &ke } } -Index shift(const Index& in_index, const Shape& shift_from) { +Index shift(const Index &in_index, const Shape &shift_from) +{ Index index = in_index; assert(index.rank() == shift_from.rank()); - for (int32_t d = 0; d < in_index.rank(); ++d) { + for (int32_t d = 0; d < in_index.rank(); ++d) + { index.at(d) = index.at(d) + shift_from.dim(d); } return index; diff --git a/compiler/nnc/passes/interpreter/ops/common.h b/compiler/nnc/passes/interpreter/ops/common.h index 577ca96..9af2264 100644 --- a/compiler/nnc/passes/interpreter/ops/common.h +++ b/compiler/nnc/passes/interpreter/ops/common.h @@ -30,8 +30,9 @@ namespace nnc /// \param[in] kernelIndex current kernel element /// \param[in] strides /// \param[in] paddings -void translate(mir::Index &translatedIndex, const mir::Index &sourceIndex, const mir::Index &kernelIndex, - const mir::Shape &strides, const mir::Index &paddings); +void translate(mir::Index &translatedIndex, const mir::Index &sourceIndex, + const mir::Index &kernelIndex, const mir::Shape &strides, + const mir::Index &paddings); /** * Shift in_index by `shift` @@ -39,6 +40,6 @@ void translate(mir::Index &translatedIndex, const mir::Index &sourceIndex, const * @param[in] shift * @return the */ -mir::Index shift(const mir::Index& in_index, const mir::Shape& shift_from); +mir::Index shift(const mir::Index &in_index, const mir::Shape &shift_from); } // namespace nnc diff --git a/compiler/nnc/passes/onnx_frontend/ONNXImporterPass.h b/compiler/nnc/passes/onnx_frontend/ONNXImporterPass.h index 25b3da5..92e0cb0 100644 --- a/compiler/nnc/passes/onnx_frontend/ONNXImporterPass.h +++ b/compiler/nnc/passes/onnx_frontend/ONNXImporterPass.h @@ -24,7 +24,7 @@ namespace mir_onnx { - class ONNXImporterImpl; +class ONNXImporterImpl; } namespace nnc diff --git a/compiler/nnc/passes/optimizations/CombineTransposes.cpp b/compiler/nnc/passes/optimizations/CombineTransposes.cpp index 9349c96..296100f 100644 --- a/compiler/nnc/passes/optimizations/CombineTransposes.cpp +++ b/compiler/nnc/passes/optimizations/CombineTransposes.cpp @@ -20,58 +20,77 @@ #include "mir/GraphPatternMatcher.h" #include -namespace nnc { +namespace nnc +{ using namespace mir; -std::vector combineAxisOrders(const std::vector& order1, - const std::vector& order2) { +std::vector combineAxisOrders(const std::vector &order1, + const std::vector &order2) +{ assert(order1.size() == order2.size()); std::vector res(order1.size()); - for (size_t i = 0; i < order1.size(); i++) { + for (size_t i = 0; i < order1.size(); i++) + { res[order2[order1[i]]] = i; } return res; } -static bool isIdentityTranspose(const std::vector& axis_order) { - for (size_t i = 0; i < ( axis_order.size()); i++) { - if (axis_order[i] != i) { +static bool isIdentityTranspose(const std::vector &axis_order) +{ + for (size_t i = 0; i < (axis_order.size()); i++) + { + if (axis_order[i] != i) + { return false; } } return true; } -nnc::PassData nnc::CombineTransposes::run(nnc::PassData data) { - auto g = static_cast(data); +nnc::PassData nnc::CombineTransposes::run(nnc::PassData data) +{ + auto g = static_cast(data); assert(g); GraphPatternMatcher matcher(g); - auto is_tr = [](const Operation* op1) { return op1->getType() == Operation::Type::transpose; }; - std::vector> matches = matcher.matchEdge(is_tr, is_tr); - std::unordered_set deleted_nodes; - while (!matches.empty()) { - for (std::pair match : matches) { - if (deleted_nodes.find(match.first) != deleted_nodes.end()) { break; }; - auto* top_transpose = dynamic_cast(match.first); - if (deleted_nodes.find(match.second) != deleted_nodes.end()) { break; }; - auto* bottom_transpose = dynamic_cast(match.second); - auto combined_axis_order = combineAxisOrders(top_transpose->getAxisOrder(), - bottom_transpose->getAxisOrder()); + auto is_tr = [](const Operation *op1) { return op1->getType() == Operation::Type::transpose; }; + std::vector> matches = matcher.matchEdge(is_tr, is_tr); + std::unordered_set deleted_nodes; + while (!matches.empty()) + { + for (std::pair match : matches) + { + if (deleted_nodes.find(match.first) != deleted_nodes.end()) + { + break; + }; + auto *top_transpose = dynamic_cast(match.first); + if (deleted_nodes.find(match.second) != deleted_nodes.end()) + { + break; + }; + auto *bottom_transpose = dynamic_cast(match.second); + auto combined_axis_order = + combineAxisOrders(top_transpose->getAxisOrder(), bottom_transpose->getAxisOrder()); - if (!isIdentityTranspose(combined_axis_order)) { - auto new_tr_op = g->create( - top_transpose->getName() + "new", - top_transpose->getInput(0)->getProducer(), combined_axis_order); + if (!isIdentityTranspose(combined_axis_order)) + { + auto new_tr_op = g->create(top_transpose->getName() + "new", + top_transpose->getInput(0)->getProducer(), + combined_axis_order); g->replaceNode(bottom_transpose, new_tr_op); - } else { + } + else + { // Connect top input to all outputs of bottom - Operation* top = top_transpose->getInput(0)->getProducer()->getNode(); + Operation *top = top_transpose->getInput(0)->getProducer()->getNode(); g->replaceNode(bottom_transpose, top); } deleted_nodes.emplace(bottom_transpose); - if (top_transpose->getOutput(0)->getConsumers().empty()) { + if (top_transpose->getOutput(0)->getConsumers().empty()) + { g->removeNode(top_transpose); deleted_nodes.emplace(top_transpose); } @@ -81,4 +100,4 @@ nnc::PassData nnc::CombineTransposes::run(nnc::PassData data) { return g; } -} //namespace nnc +} // namespace nnc diff --git a/compiler/nnc/passes/optimizations/FuseArithmeticOps.cpp b/compiler/nnc/passes/optimizations/FuseArithmeticOps.cpp index cf9ca91..36d8270 100644 --- a/compiler/nnc/passes/optimizations/FuseArithmeticOps.cpp +++ b/compiler/nnc/passes/optimizations/FuseArithmeticOps.cpp @@ -28,45 +28,54 @@ #include -namespace nnc { +namespace nnc +{ -namespace { +namespace +{ using namespace mir; using namespace std; using namespace opt_util; using OpType = Operation::Type; -using Edge = pair; +using Edge = pair; /** * This function used to get 'ConstantOp' with weights of 'AddOp', 'MulOp' or 'Conv2DOp' * For each of these ops weights stored in second input node */ -ops::ConstantOp* getSecondInputAsConst(const Operation* op) { - assert(op->getType() == OpType::add || - op->getType() == OpType::mul || +ops::ConstantOp *getSecondInputAsConst(const Operation *op) +{ + assert(op->getType() == OpType::add || op->getType() == OpType::mul || op->getType() == OpType::conv2D); - return dynamic_cast(op->getInput(1)->getProducer()->getNode()); + return dynamic_cast(op->getInput(1)->getProducer()->getNode()); } // This function finds successive operations of given types, with ConstantOp as second input -vector findSuccessiveOpsWithConstWeights(Graph* g, OpType first_op_type, - OpType second_op_type) { +vector findSuccessiveOpsWithConstWeights(Graph *g, OpType first_op_type, + OpType second_op_type) +{ vector matches; - unordered_set matched_nodes; - for (auto* first_op: g->getNodes()) { - if (first_op->getType() == first_op_type && getSecondInputAsConst(first_op)) { - for (auto& out : first_op->getOutputs()) { - for (auto* consumer : out.getConsumers()) { - Operation* second_op = consumer->getNode(); - if (second_op->getType() == second_op_type && getSecondInputAsConst(second_op)) { - /** - * Don't match already matched nodes, so for op1->op2->op3 this function - * will return {{f1, f2}} and not {{f1, f2}, {f2, f3}} - */ + unordered_set matched_nodes; + for (auto *first_op : g->getNodes()) + { + if (first_op->getType() == first_op_type && getSecondInputAsConst(first_op)) + { + for (auto &out : first_op->getOutputs()) + { + for (auto *consumer : out.getConsumers()) + { + Operation *second_op = consumer->getNode(); + if (second_op->getType() == second_op_type && getSecondInputAsConst(second_op)) + { + /** + * Don't match already matched nodes, so for op1->op2->op3 this function + * will return {{f1, f2}} and not {{f1, f2}, {f2, f3}} + */ if (matched_nodes.find(first_op) == matched_nodes.end() && - matched_nodes.find(second_op) == matched_nodes.end()) { + matched_nodes.find(second_op) == matched_nodes.end()) + { matched_nodes.emplace(first_op); matched_nodes.emplace(second_op); matches.emplace_back(first_op, second_op); @@ -83,10 +92,11 @@ vector findSuccessiveOpsWithConstWeights(Graph* g, OpType first_op_type, * This function merges two ConstantOp into new one, by elementwise multiplication or addition * If first ConstantOp rank > 1, second one broadcasting to first by axis=0 */ -Operation* mergeConstantOps(Graph* g, const ops::ConstantOp* const1_op, - const ops::ConstantOp* const2_op, OpType merge_type) { - const auto& const1_val = const1_op->getValue(); - const auto& const2_val = const2_op->getValue(); +Operation *mergeConstantOps(Graph *g, const ops::ConstantOp *const1_op, + const ops::ConstantOp *const2_op, OpType merge_type) +{ + const auto &const1_val = const1_op->getValue(); + const auto &const2_val = const2_op->getValue(); assert(const1_val.getShape().rank() >= const2_val.getShape().rank()); assert(const2_val.getShape().rank() == 1); assert(const1_val.getShape().dim(0) == const2_val.getShape().dim(0)); @@ -97,14 +107,16 @@ Operation* mergeConstantOps(Graph* g, const ops::ConstantOp* const1_op, Tensor const2_accessor(const2_val); Tensor new_const_accessor(new_const_val); ShapeRange const1_range(const1_val.getShape()); - for (auto& idx : const1_range) { + for (auto &idx : const1_range) + { float operand1 = const1_accessor.at(idx); /** * Broadcast second ConstantOp to first one: * idx of second constant always has rank 1 and equals to first dimension of first constant idx */ float operand2 = const2_accessor.at(Index{idx.at(0)}); - switch (merge_type) { + switch (merge_type) + { case OpType::mul: new_const_accessor.at(idx) = operand1 * operand2; break; @@ -143,7 +155,8 @@ Operation* mergeConstantOps(Graph* g, const ops::ConstantOp* const1_op, * \\ // | * [Mul] | */ -bool fuseSuccessiveOps(Graph* g) { +bool fuseSuccessiveOps(Graph *g) +{ // Find all successive ops vector successive_ops; auto mul_mul_vec = findSuccessiveOpsWithConstWeights(g, OpType::mul, OpType::mul); @@ -153,7 +166,8 @@ bool fuseSuccessiveOps(Graph* g) { auto conv_mul_vec = findSuccessiveOpsWithConstWeights(g, OpType::conv2D, OpType::mul); successive_ops.insert(successive_ops.end(), conv_mul_vec.begin(), conv_mul_vec.end()); - for (auto& edge : successive_ops) { + for (auto &edge : successive_ops) + { auto const1_op = getSecondInputAsConst(edge.first); auto const2_op = getSecondInputAsConst(edge.second); assert(const1_op && const2_op); @@ -186,10 +200,12 @@ bool fuseSuccessiveOps(Graph* g) { * [Mul] | [Add] * | */ -bool sinkAddThroughMul(Graph* g) { +bool sinkAddThroughMul(Graph *g) +{ auto add_mul_edges = findSuccessiveOpsWithConstWeights(g, OpType::add, OpType::mul); - for (auto& edge : add_mul_edges) { + for (auto &edge : add_mul_edges) + { auto old_add_op = edge.first; auto old_mul_op = edge.second; auto old_add_const_op = getSecondInputAsConst(old_add_op); @@ -198,11 +214,11 @@ bool sinkAddThroughMul(Graph* g) { // Create new operations auto old_add_input = old_add_op->getInput(0)->getProducer(); - auto new_mul_op = g->copyOpWithInputs(old_mul_op, {old_add_input, ols_mul_const_op->getOutput(0)}); - auto new_add_const_op = mergeConstantOps(g, old_add_const_op, ols_mul_const_op, - OpType::mul); - auto new_add_op = g->copyOpWithInputs( - old_add_op, {new_mul_op->getOutput(0), new_add_const_op->getOutput(0)}); + auto new_mul_op = + g->copyOpWithInputs(old_mul_op, {old_add_input, ols_mul_const_op->getOutput(0)}); + auto new_add_const_op = mergeConstantOps(g, old_add_const_op, ols_mul_const_op, OpType::mul); + auto new_add_op = + g->copyOpWithInputs(old_add_op, {new_mul_op->getOutput(0), new_add_const_op->getOutput(0)}); // Replace old mul with new add and remove old nodes g->replaceNode(old_mul_op, new_add_op); @@ -214,13 +230,15 @@ bool sinkAddThroughMul(Graph* g) { return !add_mul_edges.empty(); } -} // unnamed namespace +} // unnamed namespace -nnc::PassData nnc::FuseArithmeticOps::run(nnc::PassData data) { - auto g = static_cast(data); +nnc::PassData nnc::FuseArithmeticOps::run(nnc::PassData data) +{ + auto g = static_cast(data); bool graph_changed = true; - while (graph_changed) { + while (graph_changed) + { graph_changed = false; graph_changed |= fuseSuccessiveOps(g); graph_changed |= sinkAddThroughMul(g); @@ -229,4 +247,4 @@ nnc::PassData nnc::FuseArithmeticOps::run(nnc::PassData data) { return g; } -} // namespace nnc +} // namespace nnc diff --git a/compiler/nnc/passes/optimizations/OptimizationUtils.cpp b/compiler/nnc/passes/optimizations/OptimizationUtils.cpp index 5971b73..706ddca 100644 --- a/compiler/nnc/passes/optimizations/OptimizationUtils.cpp +++ b/compiler/nnc/passes/optimizations/OptimizationUtils.cpp @@ -15,33 +15,38 @@ */ #include "passes/optimizations/OptimizationUtils.h" -namespace nnc { -namespace opt_util { +namespace nnc +{ +namespace opt_util +{ -void swapAdjacent(mir::Graph* g, mir::Operation* top, mir::Operation* bottom) { - assert( - top->getNumInputs() == bottom->getNumInputs() && top->getNumInputs() == 1 && - top->getNumInputs() == top->getNumOutputs() && - top->getNumInputs() == bottom->getNumOutputs() && "incompatible ops"); - auto& ins = top->getInputs(); - std::vector prods; +void swapAdjacent(mir::Graph *g, mir::Operation *top, mir::Operation *bottom) +{ + assert(top->getNumInputs() == bottom->getNumInputs() && top->getNumInputs() == 1 && + top->getNumInputs() == top->getNumOutputs() && + top->getNumInputs() == bottom->getNumOutputs() && "incompatible ops"); + auto &ins = top->getInputs(); + std::vector prods; prods.reserve(top->getNumInputs()); - for (auto& in: ins) { + for (auto &in : ins) + { prods.emplace_back(in.getProducer()); } - mir::Operation* new_bottom = g->copyOpWithInputs(bottom, prods); + mir::Operation *new_bottom = g->copyOpWithInputs(bottom, prods); prods.clear(); prods.reserve(new_bottom->getNumOutputs()); - for (mir::Operation::Output& out: new_bottom->getOutputs()) { + for (mir::Operation::Output &out : new_bottom->getOutputs()) + { prods.emplace_back(&out); } - mir::Operation* new_top = g->copyOpWithInputs(top, prods); + mir::Operation *new_top = g->copyOpWithInputs(top, prods); g->replaceNode(bottom, new_top); g->replaceNode(top, new_bottom); } // TODO: this function and it's usages should be removed, after DCE optimization will be implemented -void removeNodeIfUnused(mir::Graph* g, mir::Operation* op) { +void removeNodeIfUnused(mir::Graph *g, mir::Operation *op) +{ if (op->getOutput(0)->getConsumers().empty()) g->removeNode(op); } diff --git a/compiler/nnc/passes/optimizations/RemoveDeadEnds.cpp b/compiler/nnc/passes/optimizations/RemoveDeadEnds.cpp index 3ec1297..0d94274 100644 --- a/compiler/nnc/passes/optimizations/RemoveDeadEnds.cpp +++ b/compiler/nnc/passes/optimizations/RemoveDeadEnds.cpp @@ -19,11 +19,14 @@ using namespace mir; -nnc::PassData nnc::RemoveDeadEnds::run(PassData data) { - auto g = static_cast(data); +nnc::PassData nnc::RemoveDeadEnds::run(PassData data) +{ + auto g = static_cast(data); assert(g); - for (auto op: g->getNodes()) { - if (op->getOutput(0)->getConsumers().empty() && op->getType() == mir::Operation::Type::constant) { + for (auto op : g->getNodes()) + { + if (op->getOutput(0)->getConsumers().empty() && op->getType() == mir::Operation::Type::constant) + { g->removeNode(op); } } diff --git a/compiler/nnc/passes/optimizations/SinkRelu.cpp b/compiler/nnc/passes/optimizations/SinkRelu.cpp index 8cfafee..5b6ef3b 100644 --- a/compiler/nnc/passes/optimizations/SinkRelu.cpp +++ b/compiler/nnc/passes/optimizations/SinkRelu.cpp @@ -26,48 +26,55 @@ #include #include -namespace nnc { +namespace nnc +{ using namespace mir; using namespace opt_util; -PassData SinkRelu::run(PassData data) { - auto g = static_cast(data); +PassData SinkRelu::run(PassData data) +{ + auto g = static_cast(data); assert(g); GraphPatternMatcher matcher(g); - auto is_relu = [](const Operation* op) { return op->getType() == Operation::Type::ReLU; }; - auto is_concat = [](const Operation* op) { return op->getType() == Operation::Type::concat; }; - auto is_max_pool = [](const Operation* op) { - auto* p_op = dynamic_cast(op); - if (!p_op) return false; + auto is_relu = [](const Operation *op) { return op->getType() == Operation::Type::ReLU; }; + auto is_concat = [](const Operation *op) { return op->getType() == Operation::Type::concat; }; + auto is_max_pool = [](const Operation *op) { + auto *p_op = dynamic_cast(op); + if (!p_op) + return false; return p_op->getPoolingType() == ops::PoolOp::PoolingType::MAX; }; - std::vector> matches; + std::vector> matches; // sink ReLU through MaxPool matches = matcher.matchEdge(is_relu, is_max_pool); - for (auto pair: matches) { + for (auto pair : matches) + { swapAdjacent(g, pair.first, pair.second); } // sink ReLU through Concat auto matches_v = matcher.matchUpBush(is_relu, is_concat); - for (const auto& pair : matches_v) { + for (const auto &pair : matches_v) + { auto relus = pair.first; - auto* concat = dynamic_cast(pair.second); - std::vector pre_relu; + auto *concat = dynamic_cast(pair.second); + std::vector pre_relu; pre_relu.reserve(relus.size()); - for (auto* r : relus) { + for (auto *r : relus) + { pre_relu.emplace_back(r->getInput(0)->getProducer()); } // create replacement nodes - auto new_concat = g->create( - concat->getName() + "_before_relu", pre_relu, concat->getAxis()); - auto new_relu = g->create( - relus[0]->getName() + "_after_concat", new_concat->getOutput(0)); + auto new_concat = + g->create(concat->getName() + "_before_relu", pre_relu, concat->getAxis()); + auto new_relu = + g->create(relus[0]->getName() + "_after_concat", new_concat->getOutput(0)); // concat is deleted here g->replaceNode(concat, new_relu); - for (auto r: relus) { + for (auto r : relus) + { removeNodeIfUnused(g, r); } } diff --git a/compiler/nnc/passes/optimizations/SinkTranspose.cpp b/compiler/nnc/passes/optimizations/SinkTranspose.cpp index 351e29f..39389a0 100644 --- a/compiler/nnc/passes/optimizations/SinkTranspose.cpp +++ b/compiler/nnc/passes/optimizations/SinkTranspose.cpp @@ -25,48 +25,54 @@ #include #include -namespace nnc { +namespace nnc +{ using namespace mir; using namespace opt_util; -PassData SinkTranspose::run(PassData data) { - auto g = static_cast(data); +PassData SinkTranspose::run(PassData data) +{ + auto g = static_cast(data); assert(g); // NOLINT GraphPatternMatcher matcher(g); - auto is_tr = [](const Operation* op1) { return op1->getType() == Operation::Type::transpose; }; - auto is_relu = [](const Operation* op2) { return op2->getType() == Operation::Type::ReLU; }; - auto is_concat = [](const Operation* op2) { return op2->getType() == Operation::Type::concat; }; - std::vector> matches; + auto is_tr = [](const Operation *op1) { return op1->getType() == Operation::Type::transpose; }; + auto is_relu = [](const Operation *op2) { return op2->getType() == Operation::Type::ReLU; }; + auto is_concat = [](const Operation *op2) { return op2->getType() == Operation::Type::concat; }; + std::vector> matches; // sink transpose below ReLU matches = matcher.matchEdge(is_tr, is_relu); - for (auto pair : matches) { + for (auto pair : matches) + { swapAdjacent(g, pair.first, pair.second); } // sink transpose through Concat auto v_matches = matcher.matchUpBush(is_tr, is_concat); - for (const auto& pair : v_matches) { - std::vector trs = pair.first; - auto* concat = dynamic_cast(pair.second); - auto axis_order = dynamic_cast(trs[0])->getAxisOrder(); - if (std::all_of( trs.begin(), trs.end(), [&axis_order](Operation* tr) { - return dynamic_cast(tr)->getAxisOrder() == axis_order; - })) { - std::vector prev_trans; + for (const auto &pair : v_matches) + { + std::vector trs = pair.first; + auto *concat = dynamic_cast(pair.second); + auto axis_order = dynamic_cast(trs[0])->getAxisOrder(); + if (std::all_of(trs.begin(), trs.end(), [&axis_order](Operation *tr) { + return dynamic_cast(tr)->getAxisOrder() == axis_order; + })) + { + std::vector prev_trans; prev_trans.reserve(trs.size()); - for (auto transpose : trs) { + for (auto transpose : trs) + { prev_trans.emplace_back(transpose->getInput(0)->getProducer()); } - auto new_concat = g->create( - concat->getName() + "_transposed", prev_trans, axis_order[concat->getAxis()]); + auto new_concat = g->create(concat->getName() + "_transposed", prev_trans, + axis_order[concat->getAxis()]); auto new_transpose = g->create(trs[0]->getName() + "_after_concat", - new_concat->getOutput(0), - axis_order); + new_concat->getOutput(0), axis_order); // removes old concat g->replaceNode(concat, new_transpose); - for (auto tr: trs) { + for (auto tr : trs) + { removeNodeIfUnused(g, tr); } } diff --git a/compiler/nnc/passes/soft_backend/BaseGenerator.cpp b/compiler/nnc/passes/soft_backend/BaseGenerator.cpp index 2c8baee..a1ce337 100644 --- a/compiler/nnc/passes/soft_backend/BaseGenerator.cpp +++ b/compiler/nnc/passes/soft_backend/BaseGenerator.cpp @@ -35,9 +35,11 @@ using namespace std; -namespace nnc { +namespace nnc +{ -namespace { +namespace +{ /** * @brief Creates pointer to some output stream to encapsulate resource management into deleter @@ -46,7 +48,8 @@ namespace { * @return Pointer output stream * @throws PluginException if did not succeed */ -unique_ptr getStream(const string& path) { +unique_ptr getStream(const string &path) +{ unique_ptr ofs(new ofstream(path)); if (ofs->fail()) throw PassException("Can not open code output file: " + path); @@ -58,22 +61,26 @@ unique_ptr getStream(const string& path) { * @param path Path to desired directory * @throws PluginException in did not succeed */ -void createDir(const string& path) { - int res = mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); // NOLINT(hicpp-signed-bitwise) +void createDir(const string &path) +{ + int res = + mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); // NOLINT(hicpp-signed-bitwise) if (res != 0 && errno != EEXIST) throw PassException("Failed to create output directory"); } } // unnamed namespace -BaseCodeGenerator::BaseCodeGenerator() { +BaseCodeGenerator::BaseCodeGenerator() +{ string base_path = cli::artifactDir + "/" + cli::artifactName; _headerPath = base_path + ".h"; _codePath = base_path + ".cpp"; _paramsPath = base_path + ".params"; } -void BaseCodeGenerator::materializeModelParams(ostream& out, const Serializer& s) { +void BaseCodeGenerator::materializeModelParams(ostream &out, const Serializer &s) +{ using namespace params; // First form a dump header @@ -89,14 +96,15 @@ void BaseCodeGenerator::materializeModelParams(ostream& out, const Serializer& s out.write(header, HEADER_LEN); if (out.fail()) throw PassException("Failed to write model parameters header"); - auto& params = s.getBuffer(); + auto ¶ms = s.getBuffer(); out.write(params.data(), params.size()); if (out.fail()) throw PassException("Failed to write model Parameters"); } -PassData BaseCodeGenerator::run(PassData data) { - auto g = static_cast(data); +PassData BaseCodeGenerator::run(PassData data) +{ + auto g = static_cast(data); assert(g); // visit and analyze graph diff --git a/compiler/nnc/passes/soft_backend/CGenerator.cpp b/compiler/nnc/passes/soft_backend/CGenerator.cpp index 5b3796d..ab8319c 100644 --- a/compiler/nnc/passes/soft_backend/CGenerator.cpp +++ b/compiler/nnc/passes/soft_backend/CGenerator.cpp @@ -19,22 +19,27 @@ using namespace std; -namespace nnc { +namespace nnc +{ -void CCodeGenerator::formatTensorNames(const ModelAnalyzer& /*ma*/) { +void CCodeGenerator::formatTensorNames(const ModelAnalyzer & /*ma*/) +{ // TODO format tensor names according to c backend requirements } -void CCodeGenerator::materializeHeader(ostream& /*out*/, const ModelAnalyzer& /*ma*/) { +void CCodeGenerator::materializeHeader(ostream & /*out*/, const ModelAnalyzer & /*ma*/) +{ // TODO emit C header to out stream } -void CCodeGenerator::materializeCode(ostream& /*out*/, const ModelAnalyzer& /*ma*/, - const Serializer& /*s*/) { +void CCodeGenerator::materializeCode(ostream & /*out*/, const ModelAnalyzer & /*ma*/, + const Serializer & /*s*/) +{ // TODO emit C code to out stream } -Pass& CCodeGenerator::getInstance() { +Pass &CCodeGenerator::getInstance() +{ static CCodeGenerator instance; return instance; } diff --git a/compiler/nnc/passes/soft_backend/CPPGenerator.cpp b/compiler/nnc/passes/soft_backend/CPPGenerator.cpp index f8d156d..38b9be8 100644 --- a/compiler/nnc/passes/soft_backend/CPPGenerator.cpp +++ b/compiler/nnc/passes/soft_backend/CPPGenerator.cpp @@ -55,7 +55,8 @@ using namespace std; #include "cpp_gather.generated.h" #include "cpp_gemm.generated.h" -namespace nnc { +namespace nnc +{ using namespace sir; @@ -65,18 +66,24 @@ using TensorType = TensorDescriptor::Type; * @brief Renames tensors with respect to C++ naming conventions * @param ma Intermediate artifact information */ -void CPPCodeGenerator::formatTensorNames(const ModelAnalyzer& ma) { +void CPPCodeGenerator::formatTensorNames(const ModelAnalyzer &ma) +{ int tmp_tensors = 0; - for (const TensorDescriptor& td: ma.getTensors()) { + for (const TensorDescriptor &td : ma.getTensors()) + { string formatted_name; - if (td.name.empty()) { + if (td.name.empty()) + { assert(td.type == TensorType::temporary); formatted_name = "Tensor_" + to_string(tmp_tensors++); - } else { + } + else + { if (td.type != TensorType::temporary) formatted_name.append("_"); formatted_name.append(td.name); - for (char& c: formatted_name) { + for (char &c : formatted_name) + { if (!isalnum(c)) c = '_'; } @@ -92,42 +99,53 @@ void CPPCodeGenerator::formatTensorNames(const ModelAnalyzer& ma) { * network constructor, setters to feed data to network, getters to get results, * and doInference method that performs actual inference. */ -void CPPCodeGenerator::materializeHeader(ostream& out, const ModelAnalyzer& ma) { +void CPPCodeGenerator::materializeHeader(ostream &out, const ModelAnalyzer &ma) +{ string class_name = ma.getModelName() + "Model"; out.write(cpp_header_types, sizeof(cpp_header_types)); out << "class " << class_name << "\n" - "{\n" - "public:\n" - " " << class_name << "(const std::string& parametersPath);\n" - " ~" << class_name << "();\n"; + "{\n" + "public:\n" + " " + << class_name << "(const std::string& parametersPath);\n" + " ~" + << class_name << "();\n"; // generate input setters if (ma.getInputs().size() == 1) out << " bool setInput(const Tensor& inputs);\n"; - for (const size_t inId: ma.getInputs()) { - const string& tName = _formattedTensors[inId]; + for (const size_t inId : ma.getInputs()) + { + const string &tName = _formattedTensors[inId]; out << " bool set" << tName << "(const Tensor& t);\n"; } // generate output getters - if (ma.getOutputs().size() == 1) { + if (ma.getOutputs().size() == 1) + { out << " std::shared_ptr getOutput();\n"; } - for (const size_t out_id: ma.getPersistentTensors()) { - const string& tensor_name = _formattedTensors[out_id]; + for (const size_t out_id : ma.getPersistentTensors()) + { + const string &tensor_name = _formattedTensors[out_id]; out << " std::shared_ptr get" << tensor_name << "();\n"; } out << " void doInference();\n\n" "private:\n" - " " << class_name << "() = delete;\n" - " " << class_name << "(const " << class_name << "& orig) = delete;\n" - " " << class_name << "& operator=(const " << class_name << "& orig) = delete;\n"; + " " + << class_name << "() = delete;\n" + " " + << class_name << "(const " << class_name << "& orig) = delete;\n" + " " + << class_name << "& operator=(const " << class_name << "& orig) = delete;\n"; // generate input/output tensors - for (const size_t in_tensor_id: ma.getInputs()) { - const string& tName = _formattedTensors[in_tensor_id]; + for (const size_t in_tensor_id : ma.getInputs()) + { + const string &tName = _formattedTensors[in_tensor_id]; out << " Tensor " << tName << ";\n"; } - for (const size_t out_tensor_id: ma.getPersistentTensors()) { - const string& tName = _formattedTensors[out_tensor_id]; + for (const size_t out_tensor_id : ma.getPersistentTensors()) + { + const string &tName = _formattedTensors[out_tensor_id]; out << " std::shared_ptr " << tName << ";\n"; } // pointer to NN parameters @@ -141,9 +159,11 @@ void CPPCodeGenerator::materializeHeader(ostream& out, const ModelAnalyzer& ma) * @param out Stream to write program text * @param args arguments to print */ -static void printOperationArgs(ostream& out, const vector& args) { +static void printOperationArgs(ostream &out, const vector &args) +{ bool insert_comma = false; - for (const string& arg: args) { + for (const string &arg : args) + { if (insert_comma) out << ", "; insert_comma = true; @@ -151,12 +171,13 @@ static void printOperationArgs(ostream& out, const vector& args) { } } -void CPPCodeGenerator::gatherOperationArguments(const ModelAnalyzer& ma, - const vector& arg_ids, - vector& args) { +void CPPCodeGenerator::gatherOperationArguments(const ModelAnalyzer &ma, + const vector &arg_ids, vector &args) +{ - for (size_t id: arg_ids) { - const string& tensor_name = _formattedTensors[id]; + for (size_t id : arg_ids) + { + const string &tensor_name = _formattedTensors[id]; if (ma.getTensors()[id].type == TensorDescriptor::Type::persistent) args.push_back("*" + tensor_name); else @@ -164,48 +185,51 @@ void CPPCodeGenerator::gatherOperationArguments(const ModelAnalyzer& ma, } } -void CPPCodeGenerator::printSetter(ostream& out, - const string& class_name, - const string& setter_name, - const TensorDescriptor& td) { +void CPPCodeGenerator::printSetter(ostream &out, const string &class_name, + const string &setter_name, const TensorDescriptor &td) +{ - const string& var_name = _formattedTensors[td.id]; + const string &var_name = _formattedTensors[td.id]; out << "bool " << class_name << "::set" << setter_name << "(const Tensor& t)\n" - "{\n"; + "{\n"; // need to insert input correctness check const mir::Shape expected = td.shape; int rank = expected.rank(); - if (rank != 0) { - out << " " << "if (t.getShape().getDims() != " << td.shape.rank() << ") return false;\n"; + if (rank != 0) + { + out << " " + << "if (t.getShape().getDims() != " << td.shape.rank() << ") return false;\n"; for (int i = 0; i < rank; ++i) - out << " " << "if (t.getShape()[" << i << "] != " << expected.dim(i) << ") return false;\n"; + out << " " + << "if (t.getShape()[" << i << "] != " << expected.dim(i) << ") return false;\n"; } out << " " << var_name << " = t;\n" - " return true;\n" - "}\n\n"; + " return true;\n" + "}\n\n"; } -void CPPCodeGenerator::printGetter(ostream& out, - const string& class_name, - const string& getter_name, - const TensorDescriptor& td) { +void CPPCodeGenerator::printGetter(ostream &out, const string &class_name, + const string &getter_name, const TensorDescriptor &td) +{ - const string& var_name = _formattedTensors[td.id]; - out << "shared_ptr " << class_name <<"::get" << getter_name << "()\n" - "{\n" - " return " << var_name << ";\n" - "}\n\n"; + const string &var_name = _formattedTensors[td.id]; + out << "shared_ptr " << class_name << "::get" << getter_name << "()\n" + "{\n" + " return " + << var_name << ";\n" + "}\n\n"; } -void CPPCodeGenerator::materializeCall(ostream& out, const ModelAnalyzer& ma, - const sir::CallFunction* call) { +void CPPCodeGenerator::materializeCall(ostream &out, const ModelAnalyzer &ma, + const sir::CallFunction *call) +{ assert(call != nullptr); if (call->mirOp->getType() == mir::Operation::Type::input) return; // materialize call out << " " << call->funcName << "("; - const auto& prev_nodes = call->mirOp->getInputs(); - const auto& out_tensors = call->outputs; + const auto &prev_nodes = call->mirOp->getInputs(); + const auto &out_tensors = call->outputs; vector args; args.reserve(prev_nodes.size() + out_tensors.size() + 1); // gather output arguments @@ -219,8 +243,9 @@ void CPPCodeGenerator::materializeCall(ostream& out, const ModelAnalyzer& ma, out << ");\n"; } -void CPPCodeGenerator::materializeTranspose(ostream& out, const ModelAnalyzer& ma, - const sir::TransposeTensor* transpose) { +void CPPCodeGenerator::materializeTranspose(ostream &out, const ModelAnalyzer &ma, + const sir::TransposeTensor *transpose) +{ assert(transpose != nullptr); (void)out; (void)ma; @@ -228,47 +253,51 @@ void CPPCodeGenerator::materializeTranspose(ostream& out, const ModelAnalyzer& m assert(false && "not implemented"); } -void CPPCodeGenerator::materializeConstructor(ostream& out, const ModelAnalyzer& ma, - const sir::CreateTmp* constructor) { +void CPPCodeGenerator::materializeConstructor(ostream &out, const ModelAnalyzer &ma, + const sir::CreateTmp *constructor) +{ assert(constructor != nullptr); - const TensorDescriptor& td = ma.getTensors()[constructor->tensorId]; + const TensorDescriptor &td = ma.getTensors()[constructor->tensorId]; assert(td.type == sir::TensorDescriptor::Type::temporary); (void)td; - const string& t_name = _formattedTensors[constructor->tensorId]; + const string &t_name = _formattedTensors[constructor->tensorId]; out << " Tensor " << t_name << ";\n"; } -void CPPCodeGenerator::materializeDestructor(ostream& out, const ModelAnalyzer& ma, - const sir::DestroyTmp* destructor) { +void CPPCodeGenerator::materializeDestructor(ostream &out, const ModelAnalyzer &ma, + const sir::DestroyTmp *destructor) +{ assert(destructor != nullptr); - const TensorDescriptor& td = ma.getTensors()[destructor->tensorId]; + const TensorDescriptor &td = ma.getTensors()[destructor->tensorId]; assert(td.type == sir::TensorDescriptor::Type::temporary); (void)td; - const string& t_name = _formattedTensors[destructor->tensorId]; + const string &t_name = _formattedTensors[destructor->tensorId]; out << " " << t_name << ".clean();\n"; } - -void CPPCodeGenerator::materializeInferenceSequence(ostream& out, const ModelAnalyzer& ma) { +void CPPCodeGenerator::materializeInferenceSequence(ostream &out, const ModelAnalyzer &ma) +{ // Allocate temporary(im2col) tensor - out << " Tensor " << _formattedTensors[ma.getTempTID()] << - "(Shape{" << ma.getMaxTemporarySize() << "});\n"; - - for (const unique_ptr& action: ma.getInferenceSequence()) { - Action* ptr = action.get(); - switch (action->type) { + out << " Tensor " << _formattedTensors[ma.getTempTID()] << "(Shape{" << ma.getMaxTemporarySize() + << "});\n"; + + for (const unique_ptr &action : ma.getInferenceSequence()) + { + Action *ptr = action.get(); + switch (action->type) + { case Action::Type::callFunction: - materializeCall(out, ma, dynamic_cast(ptr)); + materializeCall(out, ma, dynamic_cast(ptr)); break; case Action::Type::transposeTensor: - materializeTranspose(out, ma, dynamic_cast(ptr)); + materializeTranspose(out, ma, dynamic_cast(ptr)); break; case Action::Type::createTmp: - materializeConstructor(out, ma, dynamic_cast(ptr)); + materializeConstructor(out, ma, dynamic_cast(ptr)); break; case Action::Type::destroyTmp: - materializeDestructor(out, ma, dynamic_cast(ptr)); + materializeDestructor(out, ma, dynamic_cast(ptr)); break; default: assert(false && "unexpected action type"); @@ -277,9 +306,11 @@ void CPPCodeGenerator::materializeInferenceSequence(ostream& out, const ModelAna } /** - * Function writes to output stream needed code snippets, and implementations of artifact class functions. + * Function writes to output stream needed code snippets, and implementations of artifact class + * functions. */ -void CPPCodeGenerator::materializeCode(ostream& out, const ModelAnalyzer& ma, const Serializer& s) { +void CPPCodeGenerator::materializeCode(ostream &out, const ModelAnalyzer &ma, const Serializer &s) +{ string class_name = ma.getModelName() + "Model"; out << "#include \"" << cli::artifactName << ".h\"\n"; @@ -319,47 +350,53 @@ void CPPCodeGenerator::materializeCode(ostream& out, const ModelAnalyzer& ma, co out.write(cpp_leaky_relu, sizeof(cpp_leaky_relu)); // gen NN constructor - out << class_name << "::" << class_name << "(const string& parametersPath)\n" + out << class_name << "::" << class_name + << "(const string& parametersPath)\n" "{\n" " readParameters(_parameters, _paramSize, parametersPath, " << s.getFormatVersion() << ", " << s.getModelHash() << ");\n" - "}\n\n"; + "}\n\n"; // gen NN destructor out << class_name << "::~" << class_name << "()\n" - "{\n" - " releaseParameters(_parameters, _paramSize);\n" - "}\n\n"; + "{\n" + " releaseParameters(_parameters, _paramSize);\n" + "}\n\n"; // generate input setters // generate main setter if network has only one - const auto& inputs = ma.getInputs(); - const auto& tensors = ma.getTensors(); - if (inputs.size() == 1) { - const TensorDescriptor& td = tensors[inputs[0]]; + const auto &inputs = ma.getInputs(); + const auto &tensors = ma.getTensors(); + if (inputs.size() == 1) + { + const TensorDescriptor &td = tensors[inputs[0]]; printSetter(out, class_name, "Input", td); } // generate setters by names - for (size_t input_tensor_id: inputs) { - const string& input_tensor_name = _formattedTensors[input_tensor_id]; - const TensorDescriptor& td = tensors[input_tensor_id]; + for (size_t input_tensor_id : inputs) + { + const string &input_tensor_name = _formattedTensors[input_tensor_id]; + const TensorDescriptor &td = tensors[input_tensor_id]; printSetter(out, class_name, input_tensor_name, td); } // gen output getters // generate main getter if network has only one - const auto& outputs = ma.getOutputs(); - if (outputs.size() == 1) { - const TensorDescriptor& td = tensors[outputs[0]]; + const auto &outputs = ma.getOutputs(); + if (outputs.size() == 1) + { + const TensorDescriptor &td = tensors[outputs[0]]; printGetter(out, class_name, "Output", td); } - for (size_t output_tensor_id: ma.getPersistentTensors()) { - const string& output_tensor_name = _formattedTensors[output_tensor_id]; - const TensorDescriptor& td = tensors[output_tensor_id]; + for (size_t output_tensor_id : ma.getPersistentTensors()) + { + const string &output_tensor_name = _formattedTensors[output_tensor_id]; + const TensorDescriptor &td = tensors[output_tensor_id]; printGetter(out, class_name, output_tensor_name, td); } out << "void " << class_name << "::doInference()\n" - "{\n"; - for (size_t output_tensor_id: ma.getPersistentTensors()) { - const string& output_tensor_name = _formattedTensors[output_tensor_id]; + "{\n"; + for (size_t output_tensor_id : ma.getPersistentTensors()) + { + const string &output_tensor_name = _formattedTensors[output_tensor_id]; out << " " << output_tensor_name << ".reset(new Tensor());\n"; } diff --git a/compiler/nnc/passes/soft_backend/ModelAnalyzer.cpp b/compiler/nnc/passes/soft_backend/ModelAnalyzer.cpp index 20e1f08..3f72a72 100644 --- a/compiler/nnc/passes/soft_backend/ModelAnalyzer.cpp +++ b/compiler/nnc/passes/soft_backend/ModelAnalyzer.cpp @@ -25,33 +25,44 @@ using namespace std; -namespace nnc { +namespace nnc +{ using namespace mir; using namespace sir; -void ModelAnalyzer::appendOperationToInference( - Operation* op, const string& function_name, std::vector aux_args) { +void ModelAnalyzer::appendOperationToInference(Operation *op, const string &function_name, + std::vector aux_args) +{ vector node_output_tensors; - const string& op_name = op->getName(); + const string &op_name = op->getName(); // process operation outputs size_t node_output_tensor_id = INVALID_TENSOR_ID; - if (op->getType() == Operation::Type::input) { + if (op->getType() == Operation::Type::input) + { // register input tensor node_output_tensor_id = declareInputTensor(op_name, op->getOutputShape(0)); - } else if (op->getType() == Operation::Type::constant) { + } + else if (op->getType() == Operation::Type::constant) + { // register constant tensor // it's data is deserialized to described tensor by O(1) at runtime node_output_tensor_id = declareTemporaryTensor(); - } else if (op->getType() == Operation::Type::output) { + } + else if (op->getType() == Operation::Type::output) + { // process output op node_output_tensor_id = declarePersistentTensor(op_name); - } else if (!op_name.empty()) { + } + else if (!op_name.empty()) + { // process a named operation node_output_tensor_id = declarePersistentTensor(op_name); - } else { + } + else + { // process ordinary unnamed operation node_output_tensor_id = declareTemporaryTensor(); } @@ -60,29 +71,31 @@ void ModelAnalyzer::appendOperationToInference( // process operation inputs vector node_input_tensors; - for (const auto& input: op->getInputs()) { + for (const auto &input : op->getInputs()) + { size_t idx = input.getProducer()->getIndex(); - const Operation* prev_op = input.getProducer()->getNode(); + const Operation *prev_op = input.getProducer()->getNode(); assert(_opToDescr.find(prev_op) != _opToDescr.end()); - auto call = dynamic_cast(_opToDescr[prev_op]); + auto call = dynamic_cast(_opToDescr[prev_op]); assert(call); - const size_t& in_tensor_id = call->outputs[idx]; + const size_t &in_tensor_id = call->outputs[idx]; node_input_tensors.push_back(in_tensor_id); } std::copy(aux_args.begin(), aux_args.end(), std::back_inserter(node_input_tensors)); - unique_ptr operation_call(new CallFunction(op, function_name, - std::move(node_input_tensors), - std::move(node_output_tensors))); + unique_ptr operation_call(new CallFunction( + op, function_name, std::move(node_input_tensors), std::move(node_output_tensors))); _inferenceSequence.push_back(std::move(operation_call)); _opToDescr[op] = _inferenceSequence.back().get(); } -void ModelAnalyzer::updateMaxTemporarySize(const size_t size) { +void ModelAnalyzer::updateMaxTemporarySize(const size_t size) +{ _max_temp_size = std::max(_max_temp_size, size); } -size_t ModelAnalyzer::declareInputTensor(const std::string& name, const mir::Shape& shape) { +size_t ModelAnalyzer::declareInputTensor(const std::string &name, const mir::Shape &shape) +{ assert(!name.empty() && "Input tensor must have name"); size_t id = _allocatedTensors++; _tensors.push_back({id, TensorDescriptor::Type::input, name, shape}); @@ -90,37 +103,44 @@ size_t ModelAnalyzer::declareInputTensor(const std::string& name, const mir::Sha return id; } -size_t ModelAnalyzer::declarePersistentTensor(const std::string& name) { +size_t ModelAnalyzer::declarePersistentTensor(const std::string &name) +{ size_t id = _allocatedTensors++; auto type = TensorDescriptor::Type::persistent; - if (name.empty()) { + if (name.empty()) + { // special case for unnamed output tensors _tensors.push_back({id, type, "unnamed_output" + to_string(id), {}}); - } else { + } + else + { _tensors.push_back({id, type, name, {}}); } _persistent_tensors.push_back(id); return id; } -size_t ModelAnalyzer::declareTemporaryTensor() { +size_t ModelAnalyzer::declareTemporaryTensor() +{ size_t id = _allocatedTensors++; _tensors.push_back({id, TensorDescriptor::Type::temporary, "", {}}); return id; } -void ModelAnalyzer::gatherDefUseInfo(const vector>& post_order, - map& first_def, - map& last_use) { +void ModelAnalyzer::gatherDefUseInfo(const vector> &post_order, + map &first_def, map &last_use) +{ - for (size_t pos = 0; pos < post_order.size(); ++pos) { - const unique_ptr& action = post_order[pos]; - const CallFunction* call = dynamic_cast(action.get()); + for (size_t pos = 0; pos < post_order.size(); ++pos) + { + const unique_ptr &action = post_order[pos]; + const CallFunction *call = dynamic_cast(action.get()); assert(call); // update def info - for (size_t output_tensor_id : call->outputs) { - const TensorDescriptor& td = _tensors[output_tensor_id]; + for (size_t output_tensor_id : call->outputs) + { + const TensorDescriptor &td = _tensors[output_tensor_id]; if (td.type != TensorDescriptor::Type::temporary) continue; @@ -129,8 +149,9 @@ void ModelAnalyzer::gatherDefUseInfo(const vector>& post_orde } // update usage info - for (size_t input_tensor_id : call->inputs) { - const TensorDescriptor& td = _tensors[input_tensor_id]; + for (size_t input_tensor_id : call->inputs) + { + const TensorDescriptor &td = _tensors[input_tensor_id]; if (td.type != TensorDescriptor::Type::temporary) continue; @@ -139,10 +160,12 @@ void ModelAnalyzer::gatherDefUseInfo(const vector>& post_orde } } -void ModelAnalyzer::constructInferenceSequence(const vector& post_order) { +void ModelAnalyzer::constructInferenceSequence(const vector &post_order) +{ // Run inference sequence construction over constructed list of operations - for (auto it = post_order.rbegin(); it != post_order.rend(); ++it) { - Operation* node = *it; + for (auto it = post_order.rbegin(); it != post_order.rend(); ++it) + { + Operation *node = *it; node->accept(this); } @@ -164,20 +187,22 @@ void ModelAnalyzer::constructInferenceSequence(const vector& post_or old_inference_seq.swap(_inferenceSequence); _inferenceSequence.reserve(old_inference_seq.size()); - - for (size_t pos = 0; pos < old_inference_seq.size(); ++pos) { - unique_ptr& action = old_inference_seq[pos]; - const CallFunction* call = dynamic_cast(action.get()); + for (size_t pos = 0; pos < old_inference_seq.size(); ++pos) + { + unique_ptr &action = old_inference_seq[pos]; + const CallFunction *call = dynamic_cast(action.get()); assert(call); // construct required temporary tensors - for (size_t output_tensor_id : call->outputs) { - const TensorDescriptor& td = _tensors[output_tensor_id]; + for (size_t output_tensor_id : call->outputs) + { + const TensorDescriptor &td = _tensors[output_tensor_id]; assert(td.id == output_tensor_id); if (td.type != TensorDescriptor::Type::temporary) continue; - if (first_def[output_tensor_id] == pos) { + if (first_def[output_tensor_id] == pos) + { unique_ptr tmp_constructor(new CreateTmp(output_tensor_id)); _inferenceSequence.push_back(std::move(tmp_constructor)); } @@ -187,13 +212,15 @@ void ModelAnalyzer::constructInferenceSequence(const vector& post_or _inferenceSequence.push_back(std::move(action)); // destroy unused temporary tensors - for (size_t input_tensor_id : call->inputs) { - const TensorDescriptor& td = _tensors[input_tensor_id]; + for (size_t input_tensor_id : call->inputs) + { + const TensorDescriptor &td = _tensors[input_tensor_id]; assert(td.id == input_tensor_id); if (td.type != TensorDescriptor::Type::temporary) continue; - if (last_use[input_tensor_id] == pos) { + if (last_use[input_tensor_id] == pos) + { unique_ptr tmp_destructor(new DestroyTmp(input_tensor_id)); _inferenceSequence.push_back(std::move(tmp_destructor)); } @@ -201,25 +228,30 @@ void ModelAnalyzer::constructInferenceSequence(const vector& post_or } } -void ModelAnalyzer::collectOutputs(const mir::Graph* g) { - for (ops::OutputOp* out_op: g->getOutputs()) { - auto op_call = dynamic_cast(_opToDescr[out_op]); +void ModelAnalyzer::collectOutputs(const mir::Graph *g) +{ + for (ops::OutputOp *out_op : g->getOutputs()) + { + auto op_call = dynamic_cast(_opToDescr[out_op]); assert(op_call); _outputs.insert(_outputs.end(), op_call->outputs.begin(), op_call->outputs.end()); } } -void ModelAnalyzer::analyze(const mir::Graph* g) { +void ModelAnalyzer::analyze(const mir::Graph *g) +{ // Current path through graph - stack> s; + stack> s; // Nodes in Reverse Post Order stored by DFS - vector post_order; + vector post_order; // Set contains pointer to node if it is visited by DFS - set visited; + set visited; - vector init_ops; - for (Operation* op : g->getNodes()) { - if (op->getNumInputs() == 0) { + vector init_ops; + for (Operation *op : g->getNodes()) + { + if (op->getNumInputs() == 0) + { init_ops.emplace_back(op); } } @@ -228,33 +260,41 @@ void ModelAnalyzer::analyze(const mir::Graph* g) { _temp_tensor_id = declareTemporaryTensor(); // Walk all network inputs - for (Operation* in : init_ops) { - if (!visited.count(in)) { + for (Operation *in : init_ops) + { + if (!visited.count(in)) + { visited.insert(in); s.push({in, 0}); } // main DFS loop - while (!s.empty()) { + while (!s.empty()) + { // top stores current node and current outgoing edge from it - auto& top = s.top(); - Operation* node = top.first; + auto &top = s.top(); + Operation *node = top.first; auto edge = top.second++; // FIXME Refactor me. - std::vector next_nodes; - for (const auto& out : node->getOutputs()) { - const auto& consumers = out.getConsumers(); + std::vector next_nodes; + for (const auto &out : node->getOutputs()) + { + const auto &consumers = out.getConsumers(); std::transform(consumers.begin(), consumers.end(), std::back_inserter(next_nodes), - [](Operation::Input* input) { return input->getNode(); }); + [](Operation::Input *input) { return input->getNode(); }); } - if (edge == next_nodes.size()) { + if (edge == next_nodes.size()) + { // this node is fully analyzed, push it into RPO and pop from stack post_order.push_back(node); s.pop(); - } else { + } + else + { // Search current outgoing edge - Operation* successor = next_nodes[edge]; - if (!visited.count(successor)) { + Operation *successor = next_nodes[edge]; + if (!visited.count(successor)) + { visited.insert(successor); s.push({next_nodes[edge], 0}); } @@ -267,34 +307,34 @@ void ModelAnalyzer::analyze(const mir::Graph* g) { collectOutputs(g); } -void ModelAnalyzer::visit(ops::ConcatOp& op) { - appendOperationToInference(&op, "concat"); -} +void ModelAnalyzer::visit(ops::ConcatOp &op) { appendOperationToInference(&op, "concat"); } -void ModelAnalyzer::visit(ops::Conv2DOp& op) { - const auto& kernel_shape = op.getInputShape(1); - const auto& out_shape = op.getOutputShape(0); - const int32_t tmp_size = kernel_shape.dim(1) * kernel_shape.dim(2) * kernel_shape.dim(3) - * out_shape.dim(0) * out_shape.dim(1) * out_shape.dim(2); +void ModelAnalyzer::visit(ops::Conv2DOp &op) +{ + const auto &kernel_shape = op.getInputShape(1); + const auto &out_shape = op.getOutputShape(0); + const int32_t tmp_size = kernel_shape.dim(1) * kernel_shape.dim(2) * kernel_shape.dim(3) * + out_shape.dim(0) * out_shape.dim(1) * out_shape.dim(2); updateMaxTemporarySize(static_cast(tmp_size)); appendOperationToInference(&op, "conv2d", {_temp_tensor_id}); } -void ModelAnalyzer::visit(ops::DepthwiseConv2DOp& op) { +void ModelAnalyzer::visit(ops::DepthwiseConv2DOp &op) +{ appendOperationToInference(&op, "depthwiseConv2d"); } -void ModelAnalyzer::visit(ops::SoftmaxOp& op) { - appendOperationToInference(&op, "softmax"); -} +void ModelAnalyzer::visit(ops::SoftmaxOp &op) { appendOperationToInference(&op, "softmax"); } /** * Model Ir does not separate different types of pool operations, but for code generation * it is easier to implement different types of pooling by different functions */ -void ModelAnalyzer::visit(ops::PoolOp& op) { - const char* func_name = nullptr; - switch (op.getPoolingType()) { +void ModelAnalyzer::visit(ops::PoolOp &op) +{ + const char *func_name = nullptr; + switch (op.getPoolingType()) + { case ops::PoolOp::PoolingType::MAX: func_name = "maxPool"; break; @@ -307,45 +347,42 @@ void ModelAnalyzer::visit(ops::PoolOp& op) { appendOperationToInference(&op, func_name); } -void ModelAnalyzer::visit(ops::FullyConnectedOp& op) { +void ModelAnalyzer::visit(ops::FullyConnectedOp &op) +{ appendOperationToInference(&op, "fullConnect"); } -void ModelAnalyzer::visit(ops::GemmOp& op) { - appendOperationToInference(&op, "gemmOp"); -} +void ModelAnalyzer::visit(ops::GemmOp &op) { appendOperationToInference(&op, "gemmOp"); } -void ModelAnalyzer::visit(ops::CappedReluOp& op) { - appendOperationToInference(&op, "cappedRelu"); -} +void ModelAnalyzer::visit(ops::CappedReluOp &op) { appendOperationToInference(&op, "cappedRelu"); } -void ModelAnalyzer::visit(ops::InputOp& op) { +void ModelAnalyzer::visit(ops::InputOp &op) +{ assert(op.getNumInputs() == 0); appendOperationToInference(&op, "in"); } -void ModelAnalyzer::visit(ops::ConstantOp& op) { +void ModelAnalyzer::visit(ops::ConstantOp &op) +{ assert(op.getNumInputs() == 0); // FIXME This is to work around deserializeTensors not being able to deserialize tensors of type // other than float32. - const auto* output = op.getOutput(0); + const auto *output = op.getOutput(0); if (output->getConsumers().empty()) return; appendOperationToInference(&op, "constant"); } -void ModelAnalyzer::visit(ops::ReluOp& op) { - appendOperationToInference(&op, "relu"); -} +void ModelAnalyzer::visit(ops::ReluOp &op) { appendOperationToInference(&op, "relu"); } -void ModelAnalyzer::visit(ops::ReshapeOp& op) { - appendOperationToInference(&op, "reshape"); -} +void ModelAnalyzer::visit(ops::ReshapeOp &op) { appendOperationToInference(&op, "reshape"); } -void ModelAnalyzer::visit(mir::ops::ResizeOp& op) { - switch (op.getMode()) { +void ModelAnalyzer::visit(mir::ops::ResizeOp &op) +{ + switch (op.getMode()) + { case mir::ops::ResizeOp::ResizeMethod::nearestNeighbor: appendOperationToInference(&op, "resize"); break; @@ -354,49 +391,39 @@ void ModelAnalyzer::visit(mir::ops::ResizeOp& op) { } } -void ModelAnalyzer::visit(ops::DropoutOp& op) { - appendOperationToInference(&op, "dropout"); -} +void ModelAnalyzer::visit(ops::DropoutOp &op) { appendOperationToInference(&op, "dropout"); } -void ModelAnalyzer::visit(mir::ops::SliceOp& op) { - appendOperationToInference(&op, "slice"); -} +void ModelAnalyzer::visit(mir::ops::SliceOp &op) { appendOperationToInference(&op, "slice"); } -void ModelAnalyzer::visit(ops::BatchNormOp& op) { - appendOperationToInference(&op, "batchNorm"); -} +void ModelAnalyzer::visit(ops::BatchNormOp &op) { appendOperationToInference(&op, "batchNorm"); } -void ModelAnalyzer::visit(mir::ops::TanhOp& op) { +void ModelAnalyzer::visit(mir::ops::TanhOp &op) +{ appendOperationToInference(&op, "tanhActivation"); } -void ModelAnalyzer::visit(mir::ops::EluOp& op) { - appendOperationToInference(&op, "elu"); -} +void ModelAnalyzer::visit(mir::ops::EluOp &op) { appendOperationToInference(&op, "elu"); } -void ModelAnalyzer::visit(mir::ops::DeConv2DOp& op) { - const auto& kernel_shape = op.getInputShape(1); - const auto& out_shape = op.getOutputShape(0); +void ModelAnalyzer::visit(mir::ops::DeConv2DOp &op) +{ + const auto &kernel_shape = op.getInputShape(1); + const auto &out_shape = op.getOutputShape(0); const int32_t tmp_size = kernel_shape.dim(0) * kernel_shape.dim(1) * kernel_shape.dim(3) * out_shape.dim(0) * out_shape.dim(1) * out_shape.dim(2); updateMaxTemporarySize(static_cast(tmp_size)); appendOperationToInference(&op, "convTransposed2d", {_temp_tensor_id}); } -void ModelAnalyzer::visit(ops::SqueezeOp& op) { - appendOperationToInference(&op, "reshape"); -} +void ModelAnalyzer::visit(ops::SqueezeOp &op) { appendOperationToInference(&op, "reshape"); } -void ModelAnalyzer::visit(ops::SqrtOp& op) { - appendOperationToInference(&op, "sqrtFN"); -} +void ModelAnalyzer::visit(ops::SqrtOp &op) { appendOperationToInference(&op, "sqrtFN"); } -void ModelAnalyzer::visit(mir::ops::PadOp& op) { - appendOperationToInference(&op, "pad"); -} +void ModelAnalyzer::visit(mir::ops::PadOp &op) { appendOperationToInference(&op, "pad"); } -void ModelAnalyzer::visit(mir::ops::ReduceOp& op) { - switch (op.getFuncType()) { +void ModelAnalyzer::visit(mir::ops::ReduceOp &op) +{ + switch (op.getFuncType()) + { case mir::ops::ReduceOp::FuncType::mean: appendOperationToInference(&op, "reduceMean"); break; @@ -405,25 +432,21 @@ void ModelAnalyzer::visit(mir::ops::ReduceOp& op) { } } -void ModelAnalyzer::visit(mir::ops::TransposeOp& op) { +void ModelAnalyzer::visit(mir::ops::TransposeOp &op) +{ appendOperationToInference(&op, "transpose"); } -void ModelAnalyzer::visit(mir::ops::GatherOp& op) { - appendOperationToInference(&op, "gather"); -} +void ModelAnalyzer::visit(mir::ops::GatherOp &op) { appendOperationToInference(&op, "gather"); } -void ModelAnalyzer::visit(mir::ops::SigmoidOp& op) { - appendOperationToInference(&op, "sigmoid"); -} +void ModelAnalyzer::visit(mir::ops::SigmoidOp &op) { appendOperationToInference(&op, "sigmoid"); } -void ModelAnalyzer::visit(mir::ops::LeakyReluOp& op) { +void ModelAnalyzer::visit(mir::ops::LeakyReluOp &op) +{ appendOperationToInference(&op, "leakyRelu"); } -void ModelAnalyzer::visit(mir::ops::OutputOp& op) { - appendOperationToInference(&op, "out"); -} +void ModelAnalyzer::visit(mir::ops::OutputOp &op) { appendOperationToInference(&op, "out"); } void ModelAnalyzer::visit(mir::ops::AddOp &op) { diff --git a/compiler/nnc/passes/soft_backend/ModelAnalyzer.h b/compiler/nnc/passes/soft_backend/ModelAnalyzer.h index 3377f04..1bd4af4 100644 --- a/compiler/nnc/passes/soft_backend/ModelAnalyzer.h +++ b/compiler/nnc/passes/soft_backend/ModelAnalyzer.h @@ -31,111 +31,97 @@ #include #include -namespace nnc { +namespace nnc +{ /** * @brief Constructs inference sequence for given computational graph, * gathers list of variables used in artifact. */ -class ModelAnalyzer: public mir::IVisitor { +class ModelAnalyzer : public mir::IVisitor +{ public: - /** * @brief contructs inference sequence * @param g pointer to graph to linearize */ - void analyze(const mir::Graph* g); - - void visit(mir::ops::AddOp& op) override; - void visit(mir::ops::BatchNormOp& op) override; - void visit(mir::ops::CappedReluOp& op) override; - void visit(mir::ops::ConcatOp& op) override; - void visit(mir::ops::ConstantOp& op) override; - void visit(mir::ops::Conv2DOp& op) override; - void visit(mir::ops::DeConv2DOp& op) override; - void visit(mir::ops::DepthwiseConv2DOp& op) override; - void visit(mir::ops::DivOp& op) override; - void visit(mir::ops::DropoutOp& op) override; - void visit(mir::ops::EluOp& op) override; - void visit(mir::ops::FullyConnectedOp& op) override; - void visit(mir::ops::GatherOp& op) override; - void visit(mir::ops::GemmOp& op) override; - void visit(mir::ops::InputOp& op) override; - void visit(mir::ops::LeakyReluOp& op) override; - void visit(mir::ops::MaxOp& op) override; - void visit(mir::ops::MulOp& op) override; - void visit(mir::ops::OutputOp& op) override; - void visit(mir::ops::PadOp& op) override; - void visit(mir::ops::PoolOp& op) override; - void visit(mir::ops::ReduceOp& op) override; - void visit(mir::ops::ReluOp& op) override; - void visit(mir::ops::ReshapeOp& op) override; - void visit(mir::ops::ResizeOp& op) override; - void visit(mir::ops::SigmoidOp& op) override; - void visit(mir::ops::SliceOp& op) override; - void visit(mir::ops::SoftmaxOp& op) override; - void visit(mir::ops::SqrtOp& op) override; - void visit(mir::ops::SqueezeOp& op) override; - void visit(mir::ops::SubOp& op) override; - void visit(mir::ops::TanhOp& op) override; - void visit(mir::ops::TransposeOp& op) override; + void analyze(const mir::Graph *g); + + void visit(mir::ops::AddOp &op) override; + void visit(mir::ops::BatchNormOp &op) override; + void visit(mir::ops::CappedReluOp &op) override; + void visit(mir::ops::ConcatOp &op) override; + void visit(mir::ops::ConstantOp &op) override; + void visit(mir::ops::Conv2DOp &op) override; + void visit(mir::ops::DeConv2DOp &op) override; + void visit(mir::ops::DepthwiseConv2DOp &op) override; + void visit(mir::ops::DivOp &op) override; + void visit(mir::ops::DropoutOp &op) override; + void visit(mir::ops::EluOp &op) override; + void visit(mir::ops::FullyConnectedOp &op) override; + void visit(mir::ops::GatherOp &op) override; + void visit(mir::ops::GemmOp &op) override; + void visit(mir::ops::InputOp &op) override; + void visit(mir::ops::LeakyReluOp &op) override; + void visit(mir::ops::MaxOp &op) override; + void visit(mir::ops::MulOp &op) override; + void visit(mir::ops::OutputOp &op) override; + void visit(mir::ops::PadOp &op) override; + void visit(mir::ops::PoolOp &op) override; + void visit(mir::ops::ReduceOp &op) override; + void visit(mir::ops::ReluOp &op) override; + void visit(mir::ops::ReshapeOp &op) override; + void visit(mir::ops::ResizeOp &op) override; + void visit(mir::ops::SigmoidOp &op) override; + void visit(mir::ops::SliceOp &op) override; + void visit(mir::ops::SoftmaxOp &op) override; + void visit(mir::ops::SqrtOp &op) override; + void visit(mir::ops::SqueezeOp &op) override; + void visit(mir::ops::SubOp &op) override; + void visit(mir::ops::TanhOp &op) override; + void visit(mir::ops::TransposeOp &op) override; /** * @return vector of id's of network input tensors */ - const std::vector& getInputs() const { - return _inputs; - } + const std::vector &getInputs() const { return _inputs; } /** * @return vector of id's of tensors with unique names taken from Model IR */ - const std::vector& getPersistentTensors() const { - return _persistent_tensors; - } + const std::vector &getPersistentTensors() const { return _persistent_tensors; } /** * @return vector of id's of network output tensors */ - const std::vector& getOutputs() const { - return _outputs; - } + const std::vector &getOutputs() const { return _outputs; } /** * @return vector of all network tensors */ - const std::vector& getTensors() const { - return _tensors; - } + const std::vector &getTensors() const { return _tensors; } /** * @return Inference sequence */ - const std::vector>& getInferenceSequence() const { + const std::vector> &getInferenceSequence() const + { return _inferenceSequence; } /** * @return Inference sequence */ - std::vector>& getInferenceSequence() { - return _inferenceSequence; - } + std::vector> &getInferenceSequence() { return _inferenceSequence; } /** * @return Model name, taken from Model IR */ - const std::string& getModelName() const { - return _modelName; - } + const std::string &getModelName() const { return _modelName; } - size_t getMaxTemporarySize() const { - return _max_temp_size; - } + size_t getMaxTemporarySize() const { return _max_temp_size; } - size_t getTempTID() const { - return _temp_tensor_id; - } + size_t getTempTID() const { return _temp_tensor_id; } private: /** @@ -145,10 +131,10 @@ private: * @param aux_args Auxilliary argument ids * * Inserts information about CG operation into inference sequence: name of operation, - * creates tensors for operation outputs, binds operation inputs with tensors from previous operations + * creates tensors for operation outputs, binds operation inputs with tensors from previous + * operations */ - void appendOperationToInference(mir::Operation* op, - const std::string& function_name, + void appendOperationToInference(mir::Operation *op, const std::string &function_name, std::vector aux_args = {}); /** @@ -163,14 +149,14 @@ private: * @param shape expected shape of input * @return Id of created tensor */ - size_t declareInputTensor(const std::string& name, const mir::Shape& shape); + size_t declareInputTensor(const std::string &name, const mir::Shape &shape); /** * @brief Declares persistent tensor in artifact * @param name Name of variable, if empty - assigned automaticly * @return Id of created tensor */ - size_t declarePersistentTensor(const std::string& name); + size_t declarePersistentTensor(const std::string &name); /** * @brief Declares temporary tensor in artifact @@ -184,22 +170,20 @@ private: * @param first_def Maps tensor id to position in inf sequence where it was defined first time. * @param last_use Maps tensor id to position in inf sequence where it was used last time. */ - void gatherDefUseInfo(const std::vector>& post_order, - std::map& first_def, - std::map& last_use); - + void gatherDefUseInfo(const std::vector> &post_order, + std::map &first_def, std::map &last_use); /** * @brief constructs inference sequence from vector of mir::Operations, constructed * @param post_order vector representing layout of operations in inference */ - void constructInferenceSequence(const std::vector& post_order); + void constructInferenceSequence(const std::vector &post_order); /** * @brief Fill list of outputs in ModelAnalyzer * @param g Graph where to get list of outputs */ - void collectOutputs(const mir::Graph* g); + void collectOutputs(const mir::Graph *g); std::string _modelName = "NN"; std::vector> _inferenceSequence; @@ -212,7 +196,7 @@ private: size_t _max_temp_size = 0; size_t _temp_tensor_id = 0; std::vector _tensors; - std::map _opToDescr; + std::map _opToDescr; }; } // namespace nnc diff --git a/compiler/nnc/passes/soft_backend/SBSerializer.cpp b/compiler/nnc/passes/soft_backend/SBSerializer.cpp index 993c036..96580c8 100644 --- a/compiler/nnc/passes/soft_backend/SBSerializer.cpp +++ b/compiler/nnc/passes/soft_backend/SBSerializer.cpp @@ -27,7 +27,8 @@ #define UNUSED(x) ((void)(x)) -namespace nnc { +namespace nnc +{ static_assert(std::numeric_limits::is_iec559, "Unsupported float type"); @@ -40,7 +41,8 @@ using mir::TensorVariant; namespace ops = mir::ops; -namespace { +namespace +{ // Currently there are no operations with more then 4 dimensions in kernels/weights etc supported const auto MAX_DIMS = 4; const auto MAX_DIM_SIZE = numeric_limits::max(); @@ -48,17 +50,15 @@ const auto MAX_DIM_SIZE = numeric_limits::max(); const auto MAX_ENUM_VAL = numeric_limits::max(); } // unnamed namespace -void Serializer::packData(const void* data, size_t size) { - auto p = static_cast(data); +void Serializer::packData(const void *data, size_t size) +{ + auto p = static_cast(data); size_t old_size = _buffer.size(); _buffer.resize(old_size + size); copy(p, p + size, _buffer.data() + old_size); } -template -void Serializer::serializeT(const T& obj) { - packData(&obj, sizeof(T)); -} +template void Serializer::serializeT(const T &obj) { packData(&obj, sizeof(T)); } /** * @brief Convert enum to it's underlying type @@ -66,22 +66,25 @@ void Serializer::serializeT(const T& obj) { * @param enum_value Value of enum * @return Integer value that correspond to enumVal */ -template -typename underlying_type::type etoi(E enum_value) { +template typename underlying_type::type etoi(E enum_value) +{ return static_cast::type>(enum_value); } -void Serializer::serializeShape(const Shape& s) { +void Serializer::serializeShape(const Shape &s) +{ int32_t rank = s.rank(); assert(rank <= MAX_DIMS); serializeT(s.rank()); - for (int32_t i = 0; i < rank; ++i) { + for (int32_t i = 0; i < rank; ++i) + { int32_t dim = s.dim(i); serializeT(dim); } } -void Serializer::serializeTensor(const TensorVariant& t) { +void Serializer::serializeTensor(const TensorVariant &t) +{ // serialize type assert(etoi(t.getDataType()) < MAX_ENUM_VAL); serializeT(etoi(t.getDataType())); @@ -90,23 +93,25 @@ void Serializer::serializeTensor(const TensorVariant& t) { assert(element_size <= MAX_DIMS); serializeT(element_size); // serialize shape - const Shape& shape = t.getShape(); + const Shape &shape = t.getShape(); serializeShape(shape); // serialize actual data size_t data_size = element_size * shape.numElements(); size_t old_serialized_data_size = _buffer.size(); _buffer.reserve(old_serialized_data_size + data_size); - for (const Index& idx: ShapeRange(shape)) { + for (const Index &idx : ShapeRange(shape)) + { packData(t.at(idx), element_size); } } -template -void Serializer::serializePads(const Op& op, int32_t number_of_pads) { +template void Serializer::serializePads(const Op &op, int32_t number_of_pads) +{ assert(number_of_pads <= MAX_DIMS); serializeT(number_of_pads); - for (int i = 0; i < static_cast(number_of_pads); ++i) { + for (int i = 0; i < static_cast(number_of_pads); ++i) + { auto pad = op.getPaddingBefore().at(i); assert(pad <= MAX_DIM_SIZE); assert(pad >= 0); @@ -115,7 +120,8 @@ void Serializer::serializePads(const Op& op, int32_t number_of_pads) { } } -void Serializer::visit(ops::ConcatOp& op) { +void Serializer::visit(ops::ConcatOp &op) +{ _curOp->paramStartOffset = _buffer.size(); // axis number should fit into one byte assert(op.getAxis() <= MAX_DIMS); @@ -123,7 +129,8 @@ void Serializer::visit(ops::ConcatOp& op) { serializeShape(op.getOutputShape(0)); } -void Serializer::visit(ops::Conv2DOp& op) { +void Serializer::visit(ops::Conv2DOp &op) +{ _curOp->paramStartOffset = _buffer.size(); // serialize strides serializeShape(op.getStrides()); @@ -134,7 +141,8 @@ void Serializer::visit(ops::Conv2DOp& op) { serializeShape(op.getOutputShape(0)); } -void Serializer::visit(ops::DepthwiseConv2DOp& op) { +void Serializer::visit(ops::DepthwiseConv2DOp &op) +{ _curOp->paramStartOffset = _buffer.size(); // serialize strides serializeShape(op.getStrides()); @@ -145,14 +153,16 @@ void Serializer::visit(ops::DepthwiseConv2DOp& op) { serializeShape(op.getOutputShape(0)); } -void Serializer::visit(ops::SoftmaxOp& op) { +void Serializer::visit(ops::SoftmaxOp &op) +{ _curOp->paramStartOffset = _buffer.size(); // axis number should fit into one byte assert(op.getAxis() <= MAX_DIMS); serializeT(op.getAxis()); } -void Serializer::visit(ops::PoolOp& op) { +void Serializer::visit(ops::PoolOp &op) +{ _curOp->paramStartOffset = _buffer.size(); // serialize window shape serializeShape(op.getWindowShape()); @@ -163,7 +173,8 @@ void Serializer::visit(ops::PoolOp& op) { serializePads(op, number_of_pads); // serialize border type PoolBorderType border_type; - switch (op.getBorderType()) { + switch (op.getBorderType()) + { case ops::PoolOp::BorderType::EMPTY: border_type = PoolBorderType::EMPTY; break; @@ -178,70 +189,83 @@ void Serializer::visit(ops::PoolOp& op) { serializeShape(op.getOutputShape(0)); } -void Serializer::visit(ops::FullyConnectedOp& op) { +void Serializer::visit(ops::FullyConnectedOp &op) +{ _curOp->paramStartOffset = _buffer.size(); serializeShape(op.getOutputShape(0)); } -void Serializer::visit(ops::GemmOp& op) { +void Serializer::visit(ops::GemmOp &op) +{ _curOp->paramStartOffset = _buffer.size(); serializeShape(op.getOutputShape(0)); } -void Serializer::visit(ops::CappedReluOp& op) { +void Serializer::visit(ops::CappedReluOp &op) +{ _curOp->paramStartOffset = _buffer.size(); serializeT(op.getCap()); } -void Serializer::visit(ops::InputOp& /*op*/) { +void Serializer::visit(ops::InputOp & /*op*/) +{ // no parameters to dump } -void Serializer::visit(ops::ConstantOp& op) { +void Serializer::visit(ops::ConstantOp &op) +{ _curOp->paramStartOffset = _buffer.size(); serializeTensor(op.getValue()); } -void Serializer::visit(ops::ReluOp& /*op*/) { +void Serializer::visit(ops::ReluOp & /*op*/) +{ _curOp->paramStartOffset = _buffer.size(); // no parameters to dump } -void Serializer::visit(ops::ReshapeOp& op) { +void Serializer::visit(ops::ReshapeOp &op) +{ _curOp->paramStartOffset = _buffer.size(); serializeShape(op.getOutputShape(0)); } -void Serializer::visit(ops::BatchNormOp& op) { +void Serializer::visit(ops::BatchNormOp &op) +{ _curOp->paramStartOffset = _buffer.size(); serializeT(op.getEps()); serializeT(op.getMovingAvgFraction()); serializeT(op.getSpatial()); } -void Serializer::visit(mir::ops::SliceOp& op) { +void Serializer::visit(mir::ops::SliceOp &op) +{ _curOp->paramStartOffset = _buffer.size(); serializeShape(op.getStarts()); serializeShape(op.getSizes()); serializeShape(op.getOutputShape(0)); } -void Serializer::visit(ops::DropoutOp& op) { +void Serializer::visit(ops::DropoutOp &op) +{ _curOp->paramStartOffset = _buffer.size(); serializeT(op.getRate()); } -void Serializer::visit(mir::ops::TanhOp& /*op*/) { +void Serializer::visit(mir::ops::TanhOp & /*op*/) +{ _curOp->paramStartOffset = _buffer.size(); // no parameters to dump } -void Serializer::visit(mir::ops::EluOp& op) { +void Serializer::visit(mir::ops::EluOp &op) +{ _curOp->paramStartOffset = _buffer.size(); serializeT(op.getAlpha()); } -void Serializer::visit(mir::ops::DeConv2DOp& op) { +void Serializer::visit(mir::ops::DeConv2DOp &op) +{ _curOp->paramStartOffset = _buffer.size(); // serialize strides serializeShape(op.getStrides()); @@ -252,12 +276,14 @@ void Serializer::visit(mir::ops::DeConv2DOp& op) { serializeShape(op.getOutputShape(0)); } -void Serializer::visit(ops::SqueezeOp& op) { +void Serializer::visit(ops::SqueezeOp &op) +{ _curOp->paramStartOffset = _buffer.size(); serializeShape(op.getOutputShape(0)); } -void Serializer::visit(mir::ops::PadOp& op) { +void Serializer::visit(mir::ops::PadOp &op) +{ _curOp->paramStartOffset = _buffer.size(); // serialize paddings @@ -269,44 +295,50 @@ void Serializer::visit(mir::ops::PadOp& op) { // serialize num dimensions serializeT(op.getNumDim()); - for (int i = 0; i < num_dims; i++) { + for (int i = 0; i < num_dims; i++) + { std::pair pair = op.getPaddingForDim(num_dims - 1 - i); serializeT(pair.first); serializeT(pair.second); } } -void Serializer::visit(mir::ops::SqrtOp& /*op*/) { +void Serializer::visit(mir::ops::SqrtOp & /*op*/) +{ _curOp->paramStartOffset = _buffer.size(); // no parameters to dump } -void Serializer::visit(mir::ops::ResizeOp& op) { +void Serializer::visit(mir::ops::ResizeOp &op) +{ _curOp->paramStartOffset = _buffer.size(); // Result shape is the same as Output shape serializeShape(op.getOutputShape(0)); } -void Serializer::visit(mir::ops::ReduceOp& op) { +void Serializer::visit(mir::ops::ReduceOp &op) +{ _curOp->paramStartOffset = _buffer.size(); serializeShape(Shape(op.getReductionDims())); // reuse shape serialization serializeT(op.getKeepDims()); serializeShape(op.getOutputShape(0)); } -void Serializer::visit(mir::ops::TransposeOp& op) { +void Serializer::visit(mir::ops::TransposeOp &op) +{ _curOp->paramStartOffset = _buffer.size(); // serializer parameters - auto& axis_order = op.getAxisOrder(); + auto &axis_order = op.getAxisOrder(); serializeT(static_cast(axis_order.size())); - for (auto& axis : axis_order) + for (auto &axis : axis_order) serializeT(static_cast(axis)); // serialize output shape serializeShape(op.getOutputShape(0)); } -void Serializer::visit(mir::ops::GatherOp& op) { +void Serializer::visit(mir::ops::GatherOp &op) +{ _curOp->paramStartOffset = _buffer.size(); // serialize parameters serializeT(op.getAxis()); @@ -314,26 +346,28 @@ void Serializer::visit(mir::ops::GatherOp& op) { serializeShape(op.getOutputShape(0)); } -void Serializer::visit(mir::ops::SigmoidOp& /*op*/) { - _curOp->paramStartOffset = _buffer.size(); -} +void Serializer::visit(mir::ops::SigmoidOp & /*op*/) { _curOp->paramStartOffset = _buffer.size(); } -void Serializer::visit(mir::ops::LeakyReluOp& op) { +void Serializer::visit(mir::ops::LeakyReluOp &op) +{ _curOp->paramStartOffset = _buffer.size(); serializeT(op.getAlpha()); serializeShape(op.getOutputShape(0)); } -void Serializer::serialize(vector>& inference_sequence) { - for (unique_ptr& action: inference_sequence) { +void Serializer::serialize(vector> &inference_sequence) +{ + for (unique_ptr &action : inference_sequence) + { if (action->type != sir::Action::Type::callFunction) continue; - _curOp = dynamic_cast(action.get()); + _curOp = dynamic_cast(action.get()); _curOp->mirOp->accept(this); } } -void Serializer::visit(mir::ops::OutputOp& /*op*/) { +void Serializer::visit(mir::ops::OutputOp & /*op*/) +{ // no parameters to dump } diff --git a/compiler/nnc/passes/soft_backend/SBSerializer.h b/compiler/nnc/passes/soft_backend/SBSerializer.h index 4ae4364..36d58f0 100644 --- a/compiler/nnc/passes/soft_backend/SBSerializer.h +++ b/compiler/nnc/passes/soft_backend/SBSerializer.h @@ -25,7 +25,8 @@ #include #include -namespace nnc { +namespace nnc +{ /** * @brief Serializer of network parameters for soft backend @@ -37,55 +38,50 @@ namespace nnc { * To gather this vector use `getBuffer` method. * Objects of this class are one-off and not designed to serialize more than one IR */ -class Serializer : public mir::IVisitor { +class Serializer : public mir::IVisitor +{ public: - void visit(mir::ops::AddOp& op) override; - void visit(mir::ops::BatchNormOp& op) override; - void visit(mir::ops::CappedReluOp& op) override; - void visit(mir::ops::ConcatOp& op) override; - void visit(mir::ops::ConstantOp& op) override; - void visit(mir::ops::Conv2DOp& op) override; - void visit(mir::ops::DeConv2DOp& op) override; - void visit(mir::ops::DepthwiseConv2DOp& op) override; - void visit(mir::ops::DivOp& op) override; - void visit(mir::ops::DropoutOp& op) override; - void visit(mir::ops::EluOp& op) override; - void visit(mir::ops::FullyConnectedOp& op) override; - void visit(mir::ops::GatherOp& op) override; - void visit(mir::ops::GemmOp& op) override; - void visit(mir::ops::InputOp& op) override; - void visit(mir::ops::LeakyReluOp& op) override; - void visit(mir::ops::MaxOp& op) override; - void visit(mir::ops::MulOp& op) override; - void visit(mir::ops::OutputOp& op) override; - void visit(mir::ops::PadOp& op) override; - void visit(mir::ops::PoolOp& op) override; - void visit(mir::ops::ReduceOp& op) override; - void visit(mir::ops::ReluOp& op) override; - void visit(mir::ops::ReshapeOp& op) override; - void visit(mir::ops::ResizeOp& op) override; - void visit(mir::ops::SigmoidOp& op) override; - void visit(mir::ops::SliceOp& op) override; - void visit(mir::ops::SoftmaxOp& op) override; - void visit(mir::ops::SqrtOp& op) override; - void visit(mir::ops::SqueezeOp& op) override; - void visit(mir::ops::SubOp& op) override; - void visit(mir::ops::TanhOp& op) override; - void visit(mir::ops::TransposeOp& op) override; + void visit(mir::ops::AddOp &op) override; + void visit(mir::ops::BatchNormOp &op) override; + void visit(mir::ops::CappedReluOp &op) override; + void visit(mir::ops::ConcatOp &op) override; + void visit(mir::ops::ConstantOp &op) override; + void visit(mir::ops::Conv2DOp &op) override; + void visit(mir::ops::DeConv2DOp &op) override; + void visit(mir::ops::DepthwiseConv2DOp &op) override; + void visit(mir::ops::DivOp &op) override; + void visit(mir::ops::DropoutOp &op) override; + void visit(mir::ops::EluOp &op) override; + void visit(mir::ops::FullyConnectedOp &op) override; + void visit(mir::ops::GatherOp &op) override; + void visit(mir::ops::GemmOp &op) override; + void visit(mir::ops::InputOp &op) override; + void visit(mir::ops::LeakyReluOp &op) override; + void visit(mir::ops::MaxOp &op) override; + void visit(mir::ops::MulOp &op) override; + void visit(mir::ops::OutputOp &op) override; + void visit(mir::ops::PadOp &op) override; + void visit(mir::ops::PoolOp &op) override; + void visit(mir::ops::ReduceOp &op) override; + void visit(mir::ops::ReluOp &op) override; + void visit(mir::ops::ReshapeOp &op) override; + void visit(mir::ops::ResizeOp &op) override; + void visit(mir::ops::SigmoidOp &op) override; + void visit(mir::ops::SliceOp &op) override; + void visit(mir::ops::SoftmaxOp &op) override; + void visit(mir::ops::SqrtOp &op) override; + void visit(mir::ops::SqueezeOp &op) override; + void visit(mir::ops::SubOp &op) override; + void visit(mir::ops::TanhOp &op) override; + void visit(mir::ops::TransposeOp &op) override; - void serialize(std::vector>& inference_sequence); + void serialize(std::vector> &inference_sequence); - const std::vector& getBuffer() const { - return _buffer; - } + const std::vector &getBuffer() const { return _buffer; } - uint32_t getFormatVersion() const { - return _formatVersion; - } + uint32_t getFormatVersion() const { return _formatVersion; } - uint32_t getModelHash() const { - return _modelHash; - } + uint32_t getModelHash() const { return _modelHash; } private: /** @@ -93,35 +89,33 @@ private: * @param data Buffer containing data to serialize * @param size Size of data to serialize */ - void packData(const void* data, size_t size); + void packData(const void *data, size_t size); /** * @brief Serialize trivially copyable objects * @tparam T Type of object to serialize * @param obj Reference to object to serialize */ - template - void serializeT(const T& obj); + template void serializeT(const T &obj); /** * @brief Serialize Tensor shape object * @param s shape to serialize */ - void serializeShape(const mir::Shape& s); + void serializeShape(const mir::Shape &s); /** * @brief Function serializes type of given tensor base data, * it's shape and raw data in 'c' format(i.e. layout of multidimensional C array) * @param t Tensor to serialize */ - void serializeTensor(const mir::TensorVariant& t); + void serializeTensor(const mir::TensorVariant &t); /** * @brief Serialize pads for operations like Conv2D * @tparam Op Operation type * @param op Reference to operation where pads are stored * @param padsRank Number of pads to serialize */ - template - void serializePads(const Op& op, int32_t number_of_pads); + template void serializePads(const Op &op, int32_t number_of_pads); - sir::CallFunction* _curOp = nullptr; + sir::CallFunction *_curOp = nullptr; const uint32_t _formatVersion = 1; uint32_t _modelHash = 0; std::vector _buffer; @@ -130,4 +124,3 @@ private: } // namespace nnc #endif //_NNC_SOFT_BACKEND_SERIALIZER_H_ - diff --git a/compiler/nnc/passes/soft_backend/SequencedIR.h b/compiler/nnc/passes/soft_backend/SequencedIR.h index 441b495..9a76124 100644 --- a/compiler/nnc/passes/soft_backend/SequencedIR.h +++ b/compiler/nnc/passes/soft_backend/SequencedIR.h @@ -26,9 +26,11 @@ #include #include -namespace nnc { +namespace nnc +{ -namespace sir { +namespace sir +{ const size_t INVALID_TENSOR_ID = std::numeric_limits::max(); @@ -36,14 +38,16 @@ const size_t INVALID_TENSOR_ID = std::numeric_limits::max(); * @brief Represents variable used in artifact. * This variable can store inputs, outputs of network and temporary data. */ -struct TensorDescriptor { +struct TensorDescriptor +{ /** * input tensors of this type supposed to be set outside of artifact * persistent tensors store data after inference process is over, this include NN outputs * temporary tensors are not accessible outside artifact in any way, * they are created and destructed on demand */ - enum class Type { + enum class Type + { input, persistent, temporary @@ -59,7 +63,8 @@ struct TensorDescriptor { /** * @brief Action represents operation in inference sequence that is needed to */ -struct Action { +struct Action +{ /** * Defines which type of action to perform @@ -67,7 +72,8 @@ struct Action { * destroyTmp responsible for deletion of temporary tensor * transpose */ - enum class Type { + enum class Type + { createTmp, destroyTmp, callFunction, @@ -81,49 +87,48 @@ struct Action { Type type; }; -struct TransposeTensor : public Action { +struct TransposeTensor : public Action +{ - TransposeTensor(size_t input, size_t output, std::vector&& perm) - : Action(Type::transposeTensor), - perm(std::move(perm)), - input(input), - output(output) { + TransposeTensor(size_t input, size_t output, std::vector &&perm) + : Action(Type::transposeTensor), perm(std::move(perm)), input(input), output(output) + { } - std::vector perm; size_t input; size_t output; }; -struct CreateTmp : public Action { +struct CreateTmp : public Action +{ explicit CreateTmp(size_t tid) : Action(Type::createTmp), tensorId(tid) {} size_t tensorId; }; -struct DestroyTmp : public Action { +struct DestroyTmp : public Action +{ explicit DestroyTmp(size_t tid) : Action(Type::destroyTmp), tensorId(tid) {} size_t tensorId; }; -struct CallFunction : public Action { +struct CallFunction : public Action +{ - CallFunction(mir::Operation* op, std::string func_name, - std::vector&& inputs, std::vector&& outputs) - : Action(Type::callFunction), - mirOp(op), - funcName(std::move(func_name)), - inputs(inputs), - outputs(outputs), - paramStartOffset(0) {} + CallFunction(mir::Operation *op, std::string func_name, std::vector &&inputs, + std::vector &&outputs) + : Action(Type::callFunction), mirOp(op), funcName(std::move(func_name)), inputs(inputs), + outputs(outputs), paramStartOffset(0) + { + } CallFunction() : Action(Type::callFunction), mirOp(nullptr), paramStartOffset(0) {} - mir::Operation* mirOp; + mir::Operation *mirOp; std::string funcName; // list of input tensors std::vector inputs; diff --git a/compiler/nnc/support/CLOptionChecker.cpp b/compiler/nnc/support/CLOptionChecker.cpp index d4f1d90..3a00cfc 100644 --- a/compiler/nnc/support/CLOptionChecker.cpp +++ b/compiler/nnc/support/CLOptionChecker.cpp @@ -23,11 +23,14 @@ #include #include -namespace nnc { -namespace cli { - -void checkInFile(const Option &in_file) { - if ( in_file.empty() ) +namespace nnc +{ +namespace cli +{ + +void checkInFile(const Option &in_file) +{ + if (in_file.empty()) throw BadOption("Input file name should not be empty"); auto f = fopen(in_file.c_str(), "rb"); @@ -36,15 +39,17 @@ void checkInFile(const Option &in_file) { fclose(f); } // checkInFile -void checkOutFile(const Option &out_file) { - if ( out_file.empty() ) +void checkOutFile(const Option &out_file) +{ + if (out_file.empty()) throw BadOption("Output file name should not be empty"); /// @todo: if file already exists need to check accessibility } // checkOutFile -void checkInDir(const Option& dir) { +void checkInDir(const Option &dir) +{ auto stream = opendir(dir.c_str()); if (stream == nullptr) @@ -53,10 +58,12 @@ void checkInDir(const Option& dir) { closedir(stream); } // checkInDir -void checkOutDir(const Option &dir) { +void checkOutDir(const Option &dir) +{ auto stream = opendir(dir.c_str()); - if (stream == nullptr) { + if (stream == nullptr) + { // Do not consider the missing directory an error. if (errno == ENOENT) return; diff --git a/compiler/nnc/support/CommandLine.cpp b/compiler/nnc/support/CommandLine.cpp index 16a8a9f..27078be 100644 --- a/compiler/nnc/support/CommandLine.cpp +++ b/compiler/nnc/support/CommandLine.cpp @@ -32,19 +32,19 @@ namespace nnc namespace cli { -constexpr const char* const IOption::_groupNames[]; +constexpr const char *const IOption::_groupNames[]; static std::vector splitByComma(const char *str) { const char *cur_str = str; std::vector ret; - if ( std::string(str).empty() ) + if (std::string(str).empty()) return ret; - for ( size_t i = 0, cnt = 0; str[i] != '\0'; i++ ) + for (size_t i = 0, cnt = 0; str[i] != '\0'; i++) { - if ( str[i] == ',' ) + if (str[i] == ',') { std::string name(cur_str, cnt); name.erase(remove_if(name.begin(), name.end(), isspace), name.end()); @@ -68,37 +68,33 @@ static std::vector splitByComma(const char *str) } // splitByComma -std::vector optname(const char *names) -{ - return splitByComma(names); -} +std::vector optname(const char *names) { return splitByComma(names); } -std::vector optvalues(const char *vals) -{ - return splitByComma(vals); -} +std::vector optvalues(const char *vals) { return splitByComma(vals); } std::vector separators(const char *seps) { std::vector ret; int i; - if ( std::string(seps).empty() ) + if (std::string(seps).empty()) return ret; - for ( i = 0; isspace(seps[i]); i++ ) ; + for (i = 0; isspace(seps[i]); i++) + ; - if ( seps[i] ) + if (seps[i]) { ret.push_back(seps[i]); i++; } - for ( ; seps[i] != '\0'; i++ ) + for (; seps[i] != '\0'; i++) { - if ( seps[i] == ',' ) + if (seps[i] == ',') { - for ( i++; isspace(seps[i]); i++ ) ; + for (i++; isspace(seps[i]); i++) + ; ret.push_back(seps[i]); } @@ -119,13 +115,16 @@ CommandLine *CommandLine::getParser() * @param options - vector of all options * @return maximum name length of size among all options */ -static size_t calcMaxLenOfOptionsNames(std::vector options ) { +static size_t calcMaxLenOfOptionsNames(std::vector options) +{ size_t max_len = 0, len; for (const auto opt : options) - if ( !opt->isDisabled() ) { + if (!opt->isDisabled()) + { len = 0; - for (const auto &n : opt->getNames()) len += n.length(); + for (const auto &n : opt->getNames()) + len += n.length(); max_len = (max_len < len) ? len : max_len; } @@ -139,7 +138,8 @@ static size_t calcMaxLenOfOptionsNames(std::vector options ) { * @param max_opt_name_len - maximum name length of size among all options * @param leading_spaces - leading spaces that will be printed before option name */ -static void printOption(IOption* opt, size_t max_opt_name_len, size_t leading_spaces) { +static void printOption(IOption *opt, size_t max_opt_name_len, size_t leading_spaces) +{ const auto &option_descr = opt->getOverview(); const auto &names = opt->getNames(); @@ -168,8 +168,9 @@ static void printOption(IOption* opt, size_t max_opt_name_len, size_t leading_sp // determine max length size_t max_len = calcMaxLenOfOptionsNames(_options); - for (const auto opt : _options) { - if ( opt->isDisabled() ) + for (const auto opt : _options) + { + if (opt->isDisabled()) // options that are disabled not have to be shown continue; @@ -181,10 +182,12 @@ static void printOption(IOption* opt, size_t max_opt_name_len, size_t leading_sp } // print grouped options - for (const auto& group : _grouped_options) { + for (const auto &group : _grouped_options) + { std::cerr << "Options from '" << group.second[0]->getGroupName() << "' group:" << std::endl; - for (const auto opt : group.second) { + for (const auto opt : group.second) + { printOption(opt, max_len, 4); } } @@ -199,7 +202,7 @@ void CommandLine::registerOption(IOption *opt) { auto i = _options_name.emplace(n, opt); - if ( !i.second ) + if (!i.second) { std::cerr << "option name must be unique: `" << n << "'" << std::endl; exit(EXIT_FAILURE); @@ -208,11 +211,12 @@ void CommandLine::registerOption(IOption *opt) _options.push_back(opt); - if (opt->isGrouped()) { + if (opt->isGrouped()) + { auto it = _grouped_options.find(opt->getGroup()); if (it == _grouped_options.end()) - _grouped_options.emplace(opt->getGroup(), std::vector{opt}); + _grouped_options.emplace(opt->getGroup(), std::vector{opt}); else it->second.push_back(opt); } @@ -223,17 +227,18 @@ IOption *CommandLine::findOption(const char *optname) { auto it = _options_name.find(optname); - if ( it == _options_name.end() ) + if (it == _options_name.end()) { // optname can contain separators, try // to strip these separators and repeat a search size_t i = 0; - for ( ; optname[i] != '\0' && optname[i] != '=' && optname[i] != ':'; i++ ) ; + for (; optname[i] != '\0' && optname[i] != '=' && optname[i] != ':'; i++) + ; std::string strip_optname(optname, i); it = _options_name.find(strip_optname); - if ( it == _options_name.end() ) + if (it == _options_name.end()) { // couldn't find option throw BadOption(optname, ""); @@ -242,7 +247,7 @@ IOption *CommandLine::findOption(const char *optname) { IOption *opt = it->second; - if ( opt->getSeparators().empty() ) + if (opt->getSeparators().empty()) { // couldn't find option throw BadOption(optname, ""); @@ -250,7 +255,7 @@ IOption *CommandLine::findOption(const char *optname) } } - if ( it->second->isDisabled() ) + if (it->second->isDisabled()) { // if option is disabled we don't have to recognize it throw BadOption(optname, ""); @@ -261,14 +266,15 @@ IOption *CommandLine::findOption(const char *optname) } // findOption // check that option value is correct -static void checkOptionValue(const IOption *opt, const std::string &opt_name, const std::string &val) +static void checkOptionValue(const IOption *opt, const std::string &opt_name, + const std::string &val) { auto valid_vals = opt->getValidVals(); bool is_valid = valid_vals.empty(); - for ( const auto &v: valid_vals ) + for (const auto &v : valid_vals) { - if ( v == val ) + if (v == val) { // value is valid is_valid = true; @@ -276,7 +282,7 @@ static void checkOptionValue(const IOption *opt, const std::string &opt_name, co } } - if ( !is_valid ) + if (!is_valid) { throw BadOption(opt_name, val); } @@ -290,11 +296,11 @@ const char *CommandLine::findOptionValue(const IOption *opt, const char **argv, const char *val_pos = nullptr; // search one of the separators - for ( auto s : seps ) + for (auto s : seps) { - for ( int i = 0; opt_name[i] != '\0'; i++ ) + for (int i = 0; opt_name[i] != '\0'; i++) { - if ( s == opt_name[i] ) + if (s == opt_name[i]) { // separator is found, set val_pos to symbol after it val_pos = &opt_name[i] + 1; @@ -302,7 +308,7 @@ const char *CommandLine::findOptionValue(const IOption *opt, const char **argv, } } - if ( val_pos ) + if (val_pos) { break; } @@ -312,9 +318,9 @@ const char *CommandLine::findOptionValue(const IOption *opt, const char **argv, // found then we assume that option value is the next element in argv, // but if the next element starts with '-' we suppose that option value is empty // because options start with '-' - if ( !val_pos ) + if (!val_pos) { - if ( _args_num == cur_argv + 1 ) + if (_args_num == cur_argv + 1) { val_pos = ""; } @@ -341,13 +347,12 @@ const char *CommandLine::findOptionValue(const IOption *opt, const char **argv, } // findOptionValue -const char *CommandLine::findValueForMultOption(const IOption *opt, - const std::string &opt_name, +const char *CommandLine::findValueForMultOption(const IOption *opt, const std::string &opt_name, const char **argv, int cur_argv) { const char *val_pos = nullptr; - if ( cur_argv >= _args_num ) + if (cur_argv >= _args_num) { return nullptr; } @@ -376,21 +381,25 @@ const char *CommandLine::findValueForMultOption(const IOption *opt, * @param options - all options * @return true if option was found in options */ -static bool isOptionInOptions(IOption* opt, const std::set& options) { +static bool isOptionInOptions(IOption *opt, const std::set &options) +{ - for (const auto &name : opt->getNames()) { - if (options.find(name) != options.end()) { - return true; - } + for (const auto &name : opt->getNames()) + { + if (options.find(name) != options.end()) + { + return true; } + } - return false; + return false; } // isOptionInOptions -static bool areOptionsIntersected(const std::vector grouped_options, - const std::set& all_options) { - for (const auto& opt : grouped_options) +static bool areOptionsIntersected(const std::vector grouped_options, + const std::set &all_options) +{ + for (const auto &opt : grouped_options) if (isOptionInOptions(opt, all_options)) return true; @@ -399,11 +408,13 @@ static bool areOptionsIntersected(const std::vector grouped_options, void CommandLine::checkRegisteredOptions(const std::set &cmd_args) { - for (const auto& opt : _options) { + for (const auto &opt : _options) + { if (opt->isOptional() || isOptionInOptions(opt, cmd_args)) continue; - if (opt->isGrouped()) { + if (opt->isGrouped()) + { auto it = _grouped_options.find(opt->getGroup()); assert(it != _grouped_options.end()); @@ -414,7 +425,7 @@ void CommandLine::checkRegisteredOptions(const std::set &cmd_args) // option is not found then print error message std::string options; - for ( const auto &n : opt->getNames() ) + for (const auto &n : opt->getNames()) { options += (n + " "); } @@ -426,12 +437,12 @@ void CommandLine::checkRegisteredOptions(const std::set &cmd_args) void CommandLine::checkOptions(const std::set &cmd_args) { - for ( const auto &o : _options ) + for (const auto &o : _options) { // search option from command line - for ( const auto &n : o->getNames() ) + for (const auto &n : o->getNames()) { - if ( cmd_args.find(n) == cmd_args.end() ) + if (cmd_args.find(n) == cmd_args.end()) { // name isn't found continue; @@ -448,7 +459,7 @@ void CommandLine::checkOptions(const std::set &cmd_args) } } // opt names - } // options + } // options } // checkOptions @@ -461,24 +472,24 @@ void CommandLine::parseCommandLine(int argc, const char **argv, bool check_nonop _prog_name = argv[0]; _args_num = argc; - if ( argc == 1 ) + if (argc == 1) { // empty command line usage(); } // search help option and print help if this option is passed - for ( int i = 1; i < argc; i++ ) + for (int i = 1; i < argc; i++) { - if ( !strcmp(argv[i], "-h") || !strcmp(argv[i], "--help") ) + if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { usage("", EXIT_SUCCESS); } } - for ( int i = 1; i < argc; i += (argv[i+1] == arg_val) ? 2 : 1 ) + for (int i = 1; i < argc; i += (argv[i + 1] == arg_val) ? 2 : 1) { - if ( argv[i][0] != '-' ) + if (argv[i][0] != '-') { std::string err_msg(std::string("invalid command line argument: ") + argv[i]); usage(err_msg); @@ -489,7 +500,7 @@ void CommandLine::parseCommandLine(int argc, const char **argv, bool check_nonop { opt = findOption(argv[i]); } - catch ( BadOption &e ) + catch (BadOption &e) { std::string err_msg(std::string("invalid option: ") + e.getName()); usage(err_msg); @@ -498,12 +509,11 @@ void CommandLine::parseCommandLine(int argc, const char **argv, bool check_nonop // figure out value for option try { - if ( opt->canHaveSeveralVals() ) + if (opt->canHaveSeveralVals()) { int j = i + 1; - for ( arg_val = findValueForMultOption(opt, argv[i], argv, j); - arg_val; - arg_val = findValueForMultOption(opt, argv[i], argv, j) ) + for (arg_val = findValueForMultOption(opt, argv[i], argv, j); arg_val; + arg_val = findValueForMultOption(opt, argv[i], argv, j)) { // set value for option opt->setValue(arg_val); @@ -520,7 +530,7 @@ void CommandLine::parseCommandLine(int argc, const char **argv, bool check_nonop opt->setValue(arg_val); } } - catch ( BadOption &e ) + catch (BadOption &e) { std::string optname = e.getName(); optname = optname.empty() ? argv[i] : optname; @@ -533,7 +543,7 @@ void CommandLine::parseCommandLine(int argc, const char **argv, bool check_nonop cmd_args.insert(opt->getNames()[0]); } - if ( check_nonoptional ) + if (check_nonoptional) { // check that all registered options are present in command line checkRegisteredOptions(cmd_args); @@ -544,94 +554,82 @@ void CommandLine::parseCommandLine(int argc, const char **argv, bool check_nonop } // parseCommandLine - // // specializations of setValue method for all supported option type // // string -template <> -void Option::setValue(const std::string &val) +template <> void Option::setValue(const std::string &val) { - if ( !val.empty() ) + if (!val.empty()) this->setRawValue(val); } // vector of strings -template <> -void Option>::setValue(const std::string &val) +template <> void Option>::setValue(const std::string &val) { - if ( !val.empty() ) + if (!val.empty()) this->push_back(val); } // vector of ints -template <> -void Option>::setValue(const std::string &val) +template <> void Option>::setValue(const std::string &val) { if (!val.empty()) this->push_back(stoi(val)); } // bool -template <> -void Option::setValue(const std::string &val) +template <> void Option::setValue(const std::string &val) { this->setRawValue(this->convToBool(val)); } // char -template <> -void Option::setValue(const std::string &val) +template <> void Option::setValue(const std::string &val) { - if ( !val.empty() ) + if (!val.empty()) this->setRawValue(this->convToChar(val)); } // int8 -template <> -void Option::setValue(const std::string &val) +template <> void Option::setValue(const std::string &val) { - if ( !val.empty() ) + if (!val.empty()) this->setRawValue(this->template convToNum(val)); } // int16 -template <> -void Option::setValue(const std::string &val) +template <> void Option::setValue(const std::string &val) { - if ( !val.empty() ) + if (!val.empty()) this->setRawValue(this->template convToNum(val)); } // int32 -template <> -void Option::setValue(const std::string &val) +template <> void Option::setValue(const std::string &val) { - if ( !val.empty() ) + if (!val.empty()) this->setRawValue(this->template convToNum(val)); } // uint8 -template <> -void Option::setValue(const std::string &val) +template <> void Option::setValue(const std::string &val) { - if ( !val.empty() ) + if (!val.empty()) this->setRawValue(this->template convToNum(val)); } // uint16 -template <> -void Option::setValue(const std::string &val) +template <> void Option::setValue(const std::string &val) { - if ( !val.empty() ) + if (!val.empty()) this->setRawValue(this->template convToNum(val)); } // uint32 -template <> -void Option::setValue(const std::string &val) +template <> void Option::setValue(const std::string &val) { - if ( !val.empty() ) + if (!val.empty()) this->setRawValue(this->template convToNum(val)); } diff --git a/compiler/nnc/tests/acl_soft_backend/AclCppOperations.cpp b/compiler/nnc/tests/acl_soft_backend/AclCppOperations.cpp index 54c2c65..8cbc715 100644 --- a/compiler/nnc/tests/acl_soft_backend/AclCppOperations.cpp +++ b/compiler/nnc/tests/acl_soft_backend/AclCppOperations.cpp @@ -11,8 +11,10 @@ using namespace std; static string netAddr(getenv("ODROID_NET_ADDR") ? getenv("ODROID_NET_ADDR") : ""); -static unique_ptr readTensorDataFromHdf5File(const string& file_name, vector& shape) { - try { +static unique_ptr readTensorDataFromHdf5File(const string &file_name, vector &shape) +{ + try + { H5::H5File h5File(file_name, H5F_ACC_RDONLY); auto tensor_name = h5File.getObjnameByIdx(0); auto dataset = h5File.openDataSet(tensor_name); @@ -29,7 +31,8 @@ static unique_ptr readTensorDataFromHdf5File(const string& file_name, ve int size = 1; - for (int i = 0; i < rank; ++i) { + for (int i = 0; i < rank; ++i) + { size *= dims[i]; shape.push_back(dims[i]); } @@ -37,13 +40,16 @@ static unique_ptr readTensorDataFromHdf5File(const string& file_name, ve auto result = unique_ptr(new char[size * sizeof(float)]); dataset.read(&result[0], H5::PredType::NATIVE_FLOAT); return result; - } catch (H5::FileIException&) { + } + catch (H5::FileIException &) + { return nullptr; } } // TODO: this function was copied from CPPOperations.cpp, move it to a shared place. -bool areFloatsNear(float a, float b, int32_t ulp, float eps) { +bool areFloatsNear(float a, float b, int32_t ulp, float eps) +{ assert(ulp < (1 << 23) && "this algorithm is not applicable for such large diffs"); assert(eps >= 0 && "epsilon should be positive number"); if (fabs(a - b) <= eps) @@ -60,29 +66,33 @@ bool areFloatsNear(float a, float b, int32_t ulp, float eps) { return bi - ai <= ulp; } -static void compareHdf5Files(const string& file_name1, const string& file_name2) { +static void compareHdf5Files(const string &file_name1, const string &file_name2) +{ vector shape1; auto tensor1 = readTensorDataFromHdf5File(file_name1, shape1); - float* tensorData1 = reinterpret_cast(&tensor1[0]); + float *tensorData1 = reinterpret_cast(&tensor1[0]); ASSERT_NE(tensorData1, nullptr); vector shape2; auto tensor2 = readTensorDataFromHdf5File(file_name2, shape2); - float* tensorData2 = reinterpret_cast(&tensor2[0]); + float *tensorData2 = reinterpret_cast(&tensor2[0]); ASSERT_NE(tensorData2, nullptr); ASSERT_EQ(shape1.size(), shape2.size()); int size = 1; - for (int i = 0; i < shape1.size(); ++i) { + for (int i = 0; i < shape1.size(); ++i) + { ASSERT_EQ(shape1[i], shape2[i]); size *= shape1[i]; } - for (int i = 0; i < size; ++i) { + for (int i = 0; i < size; ++i) + { ASSERT_TRUE(areFloatsNear(tensorData1[i], tensorData2[i], 32, 1e-6)); } } -static string genTmpDirName() { +static string genTmpDirName() +{ string result("/tmp/nnc_test_"); stringstream ss; ss << this_thread::get_id(); @@ -91,22 +101,26 @@ static string genTmpDirName() { return result; } -static bool runOnOdroid(const string& remote_cmd) { +static bool runOnOdroid(const string &remote_cmd) +{ string cmd = "ssh " + netAddr + " \"" + remote_cmd + "\""; return system(cmd.c_str()) == 0; } -static bool copyToOdroid(const string& src, const string& dst) { +static bool copyToOdroid(const string &src, const string &dst) +{ string cmd("scp -q " + src + " " + netAddr + ":" + dst); return system(cmd.c_str()) == 0; } -static bool copyFromOdroid(const string& src, const string& dst) { +static bool copyFromOdroid(const string &src, const string &dst) +{ string cmd("scp -q " + netAddr + ":" + src + " " + dst); return system(cmd.c_str()) == 0; } -static void runAclSystemTest(const string& name) { +static void runAclSystemTest(const string &name) +{ // Ensure the Odroid device net address was set. ASSERT_TRUE(!netAddr.empty()); @@ -126,8 +140,8 @@ static void runAclSystemTest(const string& name) { ASSERT_TRUE(copyToOdroid(binDir + "/" + name + "/AclArtifact.par", dir_name)); // Copy the model input HDF5 file to the remote device. - ASSERT_TRUE(copyToOdroid(binDir + "/" + name + "/in_" + name + "_caffe.hdf5", - dir_name + "/in.hdf5")); + ASSERT_TRUE( + copyToOdroid(binDir + "/" + name + "/in_" + name + "_caffe.hdf5", dir_name + "/in.hdf5")); // Switch to the artifact directory on the remote device and run the artifact. ASSERT_TRUE(runOnOdroid("cd " + dir_name + "; ./nnc_test")); @@ -142,42 +156,22 @@ static void runAclSystemTest(const string& name) { compareHdf5Files(binDir + "/" + name + "/ref.hdf5", binDir + "/" + name + "/out.hdf5"); } -TEST(acl_cpp_operations_test, convolution) { - runAclSystemTest("convolution"); -} +TEST(acl_cpp_operations_test, convolution) { runAclSystemTest("convolution"); } -TEST(acl_cpp_operations_test, depthwise_convolution) { - runAclSystemTest("depthwise_convolution"); -} +TEST(acl_cpp_operations_test, depthwise_convolution) { runAclSystemTest("depthwise_convolution"); } -TEST(acl_cpp_operations_test, convolution_with_bias) { - runAclSystemTest("convolution_with_bias"); -} +TEST(acl_cpp_operations_test, convolution_with_bias) { runAclSystemTest("convolution_with_bias"); } -TEST(acl_cpp_operations_test, scale) { - runAclSystemTest("scale"); -} +TEST(acl_cpp_operations_test, scale) { runAclSystemTest("scale"); } -TEST(acl_cpp_operations_test, relu) { - runAclSystemTest("relu"); -} +TEST(acl_cpp_operations_test, relu) { runAclSystemTest("relu"); } -TEST(acl_cpp_operations_test, pooling_max) { - runAclSystemTest("pooling_max"); -} +TEST(acl_cpp_operations_test, pooling_max) { runAclSystemTest("pooling_max"); } -TEST(acl_cpp_operations_test, pooling_avg) { - runAclSystemTest("pooling_avg"); -} +TEST(acl_cpp_operations_test, pooling_avg) { runAclSystemTest("pooling_avg"); } -TEST(acl_cpp_operations_test, concatenate) { - runAclSystemTest("concatenate"); -} +TEST(acl_cpp_operations_test, concatenate) { runAclSystemTest("concatenate"); } -TEST(acl_cpp_operations_test, reshape) { - runAclSystemTest("reshape"); -} +TEST(acl_cpp_operations_test, reshape) { runAclSystemTest("reshape"); } -TEST(acl_cpp_operations_test, fully_connected) { - runAclSystemTest("fully_connected"); -} +TEST(acl_cpp_operations_test, fully_connected) { runAclSystemTest("fully_connected"); } diff --git a/compiler/nnc/tests/acl_soft_backend/artifact_cmake/main.cpp b/compiler/nnc/tests/acl_soft_backend/artifact_cmake/main.cpp index 03adfa2..5dec0f3 100644 --- a/compiler/nnc/tests/acl_soft_backend/artifact_cmake/main.cpp +++ b/compiler/nnc/tests/acl_soft_backend/artifact_cmake/main.cpp @@ -6,43 +6,51 @@ using namespace std; using namespace arm_compute; -static unique_ptr getTensorData(CLTensor& tensor) { +static unique_ptr getTensorData(CLTensor &tensor) +{ auto buf = unique_ptr(new char[tensor.info()->total_size()]); tensor.map(); Window window; window.use_tensor_dimensions(tensor.info()->tensor_shape()); Iterator i(&tensor, window); - char* ptr = &buf[0]; + char *ptr = &buf[0]; - execute_window_loop(window, [&i, &ptr](const Coordinates&) { - memcpy(ptr, i.ptr(), sizeof(float)); - ptr += sizeof(float); - }, i); + execute_window_loop(window, + [&i, &ptr](const Coordinates &) { + memcpy(ptr, i.ptr(), sizeof(float)); + ptr += sizeof(float); + }, + i); tensor.unmap(); return buf; } -static void readTensor(CLTensor& tensor, H5::DataSet& dataset) { +static void readTensor(CLTensor &tensor, H5::DataSet &dataset) +{ auto buf = unique_ptr(new char[tensor.info()->total_size()]); dataset.read(&buf[0], H5::PredType::NATIVE_FLOAT); tensor.map(); Window window; window.use_tensor_dimensions(tensor.info()->tensor_shape()); Iterator i(&tensor, window); - char* ptr = &buf[0]; + char *ptr = &buf[0]; - execute_window_loop(window, [&i, &ptr](const Coordinates&) { - memcpy(i.ptr(), ptr, sizeof(float)); - ptr += sizeof(float); - }, i); + execute_window_loop(window, + [&i, &ptr](const Coordinates &) { + memcpy(i.ptr(), ptr, sizeof(float)); + ptr += sizeof(float); + }, + i); tensor.unmap(); } -static bool readTensorFromHDF5File(CLTensor& tensor, const string& file_name) { +static bool readTensorFromHDF5File(CLTensor &tensor, const string &file_name) +{ // Read from the .hdf5 file - try { + try + { H5::H5File h5File(file_name, H5F_ACC_RDONLY); auto tensor_name = h5File.getObjnameByIdx(0); auto dataset = h5File.openDataSet(tensor_name); @@ -64,17 +72,20 @@ static bool readTensorFromHDF5File(CLTensor& tensor, const string& file_name) { shape[rank - i - 1] = dims[i]; readTensor(tensor, dataset); - } catch (H5::FileIException&) { + } + catch (H5::FileIException &) + { return false; } return true; } -static void writeTensorToHDF5File(CLTensor& tensor, const string& tensor_name, - const string& file_name) { - const TensorShape& orig_shape = tensor.info()->tensor_shape(); - const TensorShape& transposed_shape = orig_shape; +static void writeTensorToHDF5File(CLTensor &tensor, const string &tensor_name, + const string &file_name) +{ + const TensorShape &orig_shape = tensor.info()->tensor_shape(); + const TensorShape &transposed_shape = orig_shape; int rank = transposed_shape.num_dimensions(); hsize_t dims[rank + 1]; dims[0] = 1; @@ -89,21 +100,23 @@ static void writeTensorToHDF5File(CLTensor& tensor, const string& tensor_name, dataset.write(&getTensorData(tensor)[0], H5::PredType::NATIVE_FLOAT); } -int main(int argc, char* argv[]) { +int main(int argc, char *argv[]) +{ CLScheduler::get().default_init(); - if (!CLScheduler::get().is_initialised()) { + if (!CLScheduler::get().is_initialised()) + { cout << "Failed to initialise the ACL scheduler" << endl; return 1; } AclArtifact artifact; - CLTensor& artifact_in = artifact.getInput(); + CLTensor &artifact_in = artifact.getInput(); readTensorFromHDF5File(artifact_in, "in.hdf5"); artifact.Inference(); - CLTensor& artifact_out = artifact.getOutput(); + CLTensor &artifact_out = artifact.getOutput(); writeTensorToHDF5File(artifact_out, "out", "out.hdf5"); return 0; diff --git a/compiler/nnc/tests/import/caffe.cpp b/compiler/nnc/tests/import/caffe.cpp index 88a42d4..1f6e400 100644 --- a/compiler/nnc/tests/import/caffe.cpp +++ b/compiler/nnc/tests/import/caffe.cpp @@ -22,7 +22,8 @@ using namespace nnc; -int main(int argc, const char **argv) { +int main(int argc, const char **argv) +{ if (argc != 2) return 1; @@ -30,10 +31,12 @@ int main(int argc, const char **argv) { nnc::CaffeImporterPass importer{cli::inputFile}; - try { + try + { importer.importModel(); } - catch (...) { + catch (...) + { std::cout << "Could not create IR for model \"" << cli::inputFile << "\"" << std::endl; return 1; } diff --git a/compiler/nnc/tests/soft_backend/CompileCPP.cpp b/compiler/nnc/tests/soft_backend/CompileCPP.cpp index ed75f17..7f64bc9 100644 --- a/compiler/nnc/tests/soft_backend/CompileCPP.cpp +++ b/compiler/nnc/tests/soft_backend/CompileCPP.cpp @@ -44,26 +44,30 @@ using namespace std; using namespace nnc; using namespace mir; - // Creates simple graph with input and output -static void fillGraph(Graph& g) { +static void fillGraph(Graph &g) +{ Shape input_shape{1, 2, 3}; - Operation* input_op = g.create("in", input_shape); - Operation* relu_op = g.create("relu", input_op->getOutput(0)); - Operation* output_op = g.create("out", relu_op->getOutput(0)); + Operation *input_op = g.create("in", input_shape); + Operation *relu_op = g.create("relu", input_op->getOutput(0)); + Operation *output_op = g.create("out", relu_op->getOutput(0)); } -static void checkFileExists(const string& path) { +static void checkFileExists(const string &path) +{ ifstream f(path); - if (!f.good()) { + if (!f.good()) + { cerr << "file " << path << " not created\n"; exit(1); } } -static void createMain(const string& path, const string& header_path) { +static void createMain(const string &path, const string &header_path) +{ ofstream out(path); - if (!out.good()) { + if (!out.good()) + { cerr << "Main file " << path << " not created\n"; exit(1); } @@ -71,7 +75,8 @@ static void createMain(const string& path, const string& header_path) { out.write(test_main, sizeof(test_main)); } -int main(int argc, const char* argv[]) { +int main(int argc, const char *argv[]) +{ cli::CommandLine::getParser()->parseCommandLine(argc, argv, false); std::string output_dir = cli::artifactDir; std::string artifact_name = cli::artifactName; @@ -102,11 +107,13 @@ int main(int argc, const char* argv[]) { // call compiler int res = system(compiler_command.c_str()); - if (res == -1) { + if (res == -1) + { cerr << "failed to call compiler\n"; return 2; } - if (res != 0) { + if (res != 0) + { cerr << "compiler did not succeed with error code " << res << ": " << compiler_command << "\n"; return 3; } diff --git a/compiler/nnc/unittests/acl_backend/DOMToText.cpp b/compiler/nnc/unittests/acl_backend/DOMToText.cpp index cda455b..be0e671 100644 --- a/compiler/nnc/unittests/acl_backend/DOMToText.cpp +++ b/compiler/nnc/unittests/acl_backend/DOMToText.cpp @@ -36,12 +36,13 @@ using namespace nnc; using AF = ArtifactFactory; -TEST(acl_backend_dom_to_text, ArtifactLiteral) { +TEST(acl_backend_dom_to_text, ArtifactLiteral) +{ stringstream code_out; stringstream decl_out; ArtifactGeneratorCppCode code_gen(code_out); ArtifactGeneratorCppDecl decl_gen(decl_out); - const char* lit_data = "hello_world"; + const char *lit_data = "hello_world"; shared_ptr lit = AF::lit(lit_data); lit->accept(&code_gen); lit->accept(&decl_gen); @@ -49,12 +50,13 @@ TEST(acl_backend_dom_to_text, ArtifactLiteral) { ASSERT_EQ(decl_out.str(), lit_data); } -TEST(acl_backend_dom_to_text, ArtifactId) { +TEST(acl_backend_dom_to_text, ArtifactId) +{ stringstream code_out; stringstream decl_out; ArtifactGeneratorCppCode code_gen(code_out); ArtifactGeneratorCppDecl decl_gen(decl_out); - const char* id_data = "some_id"; + const char *id_data = "some_id"; shared_ptr id = AF::id(id_data); id->accept(&code_gen); id->accept(&decl_gen); @@ -62,12 +64,13 @@ TEST(acl_backend_dom_to_text, ArtifactId) { ASSERT_EQ(decl_out.str(), id_data); } -TEST(acl_backend_dom_to_text, ArtifactRef) { +TEST(acl_backend_dom_to_text, ArtifactRef) +{ stringstream code_out; stringstream decl_out; ArtifactGeneratorCppCode code_gen(code_out); ArtifactGeneratorCppDecl decl_gen(decl_out); - const char* id_data = "some_id"; + const char *id_data = "some_id"; shared_ptr id = AF::id(id_data); shared_ptr ref = AF::ref(id); ref->accept(&code_gen); @@ -77,12 +80,13 @@ TEST(acl_backend_dom_to_text, ArtifactRef) { ASSERT_EQ(decl_out.str(), ref_data); } -TEST(acl_backend_dom_to_text, ArtifactDeref) { +TEST(acl_backend_dom_to_text, ArtifactDeref) +{ stringstream code_out; stringstream decl_out; ArtifactGeneratorCppCode code_gen(code_out); ArtifactGeneratorCppDecl decl_gen(decl_out); - const char* id_data = "some_id"; + const char *id_data = "some_id"; shared_ptr id = AF::id(id_data); shared_ptr deref = AF::deref(id); deref->accept(&code_gen); @@ -92,11 +96,10 @@ TEST(acl_backend_dom_to_text, ArtifactDeref) { ASSERT_EQ(decl_out.str(), ref_data); } -static void checkCall(ArtifactCallType type, - const char* call_name, - const list>& args, - shared_ptr obj, - const char* ref_data) { +static void checkCall(ArtifactCallType type, const char *call_name, + const list> &args, shared_ptr obj, + const char *ref_data) +{ stringstream code_out; ArtifactGeneratorCppCode code_gen(code_out); shared_ptr call = AF::call(call_name, args, obj, type); @@ -104,35 +107,34 @@ static void checkCall(ArtifactCallType type, ASSERT_EQ(code_out.str(), ref_data); } -TEST(acl_backend_dom_to_text, ArtifactFunctionCall) { - const char* lit_data = "123"; - const char* id_data = "some_id"; +TEST(acl_backend_dom_to_text, ArtifactFunctionCall) +{ + const char *lit_data = "123"; + const char *id_data = "some_id"; shared_ptr id = AF::id(id_data); shared_ptr lit = AF::lit(lit_data); const list> args{id, lit}; - shared_ptr obj = AF::id("obj"); - using TestCase = tuple, const char*>; - TestCase test_cases[] = { - TestCase{ArtifactCallType::scope, nullptr, "foo(some_id, 123)"}, - TestCase{ArtifactCallType::obj, obj, "obj.foo(some_id, 123)"}, - TestCase{ArtifactCallType::ref, obj, "obj->foo(some_id, 123)"}, - TestCase{ArtifactCallType::scope, obj, "obj::foo(some_id, 123)"} - }; + using TestCase = tuple, const char *>; + TestCase test_cases[] = {TestCase{ArtifactCallType::scope, nullptr, "foo(some_id, 123)"}, + TestCase{ArtifactCallType::obj, obj, "obj.foo(some_id, 123)"}, + TestCase{ArtifactCallType::ref, obj, "obj->foo(some_id, 123)"}, + TestCase{ArtifactCallType::scope, obj, "obj::foo(some_id, 123)"}}; - for (const auto& test: test_cases) { + for (const auto &test : test_cases) + { ArtifactCallType call_type = get<0>(test); shared_ptr obj = get<1>(test); - const char* ref_output = get<2>(test); + const char *ref_output = get<2>(test); checkCall(call_type, "foo", args, obj, ref_output); } } -static void checkUnaryExpression(ArtifactUnOp op, - shared_ptr var, - const char* ref_data) { +static void checkUnaryExpression(ArtifactUnOp op, shared_ptr var, + const char *ref_data) +{ stringstream code_out; ArtifactGeneratorCppCode code_gen(code_out); @@ -141,29 +143,26 @@ static void checkUnaryExpression(ArtifactUnOp op, ASSERT_EQ(code_out.str(), ref_data); } -TEST(acl_backend_dom_to_text, ArtifactUnaryExpr) { - const char* var_name = "id"; +TEST(acl_backend_dom_to_text, ArtifactUnaryExpr) +{ + const char *var_name = "id"; shared_ptr var = AF::id(var_name); - pair test_cases[] = { - {ArtifactUnOp::preIncr, "++id"}, - {ArtifactUnOp::preDecr, "--id"}, - {ArtifactUnOp::heapNew, "new id"}, - {ArtifactUnOp::heapFree, "delete id"}, - {ArtifactUnOp::postIncr, "id++"}, - {ArtifactUnOp::postDecr, "id--"} - }; - - for (auto test: test_cases) { + pair test_cases[] = { + {ArtifactUnOp::preIncr, "++id"}, {ArtifactUnOp::preDecr, "--id"}, + {ArtifactUnOp::heapNew, "new id"}, {ArtifactUnOp::heapFree, "delete id"}, + {ArtifactUnOp::postIncr, "id++"}, {ArtifactUnOp::postDecr, "id--"}}; + + for (auto test : test_cases) + { auto op_type = test.first; auto ref_output = test.second; checkUnaryExpression(op_type, var, ref_output); } } -static void checkBinaryExpression(ArtifactBinOp op, - shared_ptr op1, - shared_ptr op2, - const char* ref_data) { +static void checkBinaryExpression(ArtifactBinOp op, shared_ptr op1, + shared_ptr op2, const char *ref_data) +{ stringstream code_out; ArtifactGeneratorCppCode code_gen(code_out); @@ -172,44 +171,39 @@ static void checkBinaryExpression(ArtifactBinOp op, ASSERT_EQ(code_out.str(), ref_data); } -TEST(acl_backend_dom_to_text, ArtifactBinaryExpr) { +TEST(acl_backend_dom_to_text, ArtifactBinaryExpr) +{ stringstream code_out; ArtifactGeneratorCppCode code_gen(code_out); - const char* op1_name = "a"; - const char* op2_name = "b"; + const char *op1_name = "a"; + const char *op2_name = "b"; shared_ptr op1 = AF::id(op1_name); shared_ptr op2 = AF::id(op2_name); - pair test_cases[] ={ - {ArtifactBinOp::eq, "a == b"}, - {ArtifactBinOp::notEq, "a != b"}, - {ArtifactBinOp::less, "a < b"}, - {ArtifactBinOp::lessOrEq, "a <= b"}, - {ArtifactBinOp::great, "a > b"}, - {ArtifactBinOp::greatOrEq, "a >= b"}, - {ArtifactBinOp::assign, "a = b"}, - {ArtifactBinOp::plus, "a + b"}, - {ArtifactBinOp::minus, "a - b"}, - {ArtifactBinOp::mult, "a * b"}, - {ArtifactBinOp::div, "a / b"}, - {ArtifactBinOp::plusAssign, "a += b"}, - {ArtifactBinOp::minusAssign, "a -= b"}, - {ArtifactBinOp::multAssign, "a *= b"}, - {ArtifactBinOp::divAssign, "a /= b"} - }; - - for (auto test: test_cases) { + pair test_cases[] = { + {ArtifactBinOp::eq, "a == b"}, {ArtifactBinOp::notEq, "a != b"}, + {ArtifactBinOp::less, "a < b"}, {ArtifactBinOp::lessOrEq, "a <= b"}, + {ArtifactBinOp::great, "a > b"}, {ArtifactBinOp::greatOrEq, "a >= b"}, + {ArtifactBinOp::assign, "a = b"}, {ArtifactBinOp::plus, "a + b"}, + {ArtifactBinOp::minus, "a - b"}, {ArtifactBinOp::mult, "a * b"}, + {ArtifactBinOp::div, "a / b"}, {ArtifactBinOp::plusAssign, "a += b"}, + {ArtifactBinOp::minusAssign, "a -= b"}, {ArtifactBinOp::multAssign, "a *= b"}, + {ArtifactBinOp::divAssign, "a /= b"}}; + + for (auto test : test_cases) + { auto op_type = test.first; auto ref_output = test.second; checkBinaryExpression(op_type, op1, op2, ref_output); } } -TEST(acl_backend_dom_to_text, ArtifactIndex) { +TEST(acl_backend_dom_to_text, ArtifactIndex) +{ stringstream code_out; ArtifactGeneratorCppCode code_gen(code_out); - const char* arr_name = "a"; - const char* idx_name = "b"; + const char *arr_name = "a"; + const char *idx_name = "b"; shared_ptr arr = AF::id(arr_name); shared_ptr idx = AF::id(idx_name); shared_ptr indexing = AF::ind(arr, idx); @@ -217,17 +211,19 @@ TEST(acl_backend_dom_to_text, ArtifactIndex) { ASSERT_EQ(code_out.str(), "a[b]"); } -TEST(acl_backend_dom_to_text, ArtifactRet) { +TEST(acl_backend_dom_to_text, ArtifactRet) +{ stringstream code_out; ArtifactGeneratorCppCode code_gen(code_out); - const char* result_name = "a"; + const char *result_name = "a"; shared_ptr result = AF::id(result_name); ArtifactRet ret(result); ret.accept(&code_gen); ASSERT_EQ(code_out.str(), "return a"); } -TEST(acl_backend_dom_to_text, ArtifactBreak) { +TEST(acl_backend_dom_to_text, ArtifactBreak) +{ stringstream code_out; ArtifactGeneratorCppCode code_gen(code_out); ArtifactBreak brk; @@ -235,7 +231,8 @@ TEST(acl_backend_dom_to_text, ArtifactBreak) { ASSERT_EQ(code_out.str(), "break"); } -TEST(acl_backend_dom_to_text, ArtifactCont) { +TEST(acl_backend_dom_to_text, ArtifactCont) +{ stringstream code_out; ArtifactGeneratorCppCode code_gen(code_out); ArtifactCont cont; @@ -243,11 +240,12 @@ TEST(acl_backend_dom_to_text, ArtifactCont) { ASSERT_EQ(code_out.str(), "continue"); } -TEST(acl_backend_dom_to_text, ArtifactVariable) { +TEST(acl_backend_dom_to_text, ArtifactVariable) +{ stringstream code_out; ArtifactGeneratorCppCode code_gen(code_out); - const char* var_type = "int"; - const char* var_name = "data"; + const char *var_type = "int"; + const char *var_name = "data"; shared_ptr dim1 = AF::lit("2"); shared_ptr dim2 = AF::lit("3"); list> dims{dim1, dim2}; @@ -258,11 +256,12 @@ TEST(acl_backend_dom_to_text, ArtifactVariable) { ASSERT_EQ(code_out.str(), "int data[2][3](123)"); } -TEST(acl_backend_dom_to_text, ArtifactBlock) { +TEST(acl_backend_dom_to_text, ArtifactBlock) +{ stringstream code_out; ArtifactGeneratorCppCode code_gen(code_out); - const char* var_name = "var"; - const char* lit_val = "123"; + const char *var_name = "var"; + const char *lit_val = "123"; shared_ptr id = AF::id(var_name); shared_ptr lit = AF::lit(lit_val); @@ -278,17 +277,21 @@ TEST(acl_backend_dom_to_text, ArtifactBlock) { ASSERT_EQ(code_out.str(), " {\n foo(var, 123);\n}\n"); } -TEST(acl_backend_dom_to_text, ArtifactForLoop) { +TEST(acl_backend_dom_to_text, ArtifactForLoop) +{ stringstream code_out; ArtifactGeneratorCppCode code_gen(code_out); - const char* var_name = "i"; - const char* var_type = "int"; + const char *var_name = "i"; + const char *var_type = "int"; shared_ptr iter = AF::var(var_type, var_name, {}, {AF::lit("0")}); - shared_ptr step = AF::bin(ArtifactBinOp::plusAssign, AF::id(var_name), AF::lit("1")); - shared_ptr cond = AF::bin(ArtifactBinOp::lessOrEq, AF::id(var_name), AF::lit("123")); + shared_ptr step = + AF::bin(ArtifactBinOp::plusAssign, AF::id(var_name), AF::lit("1")); + shared_ptr cond = + AF::bin(ArtifactBinOp::lessOrEq, AF::id(var_name), AF::lit("123")); - shared_ptr expr = AF::bin(ArtifactBinOp::plusAssign, AF::id("hello"), AF::id("world")); + shared_ptr expr = + AF::bin(ArtifactBinOp::plusAssign, AF::id("hello"), AF::id("world")); ArtifactForLoop loop(iter, cond, step); @@ -298,14 +301,17 @@ TEST(acl_backend_dom_to_text, ArtifactForLoop) { ASSERT_EQ(code_out.str(), "for(int i(0); i <= 123; i += 1) {\n hello += world;\n}\n"); } -TEST(acl_backend_dom_to_text, ArtifactIf) { +TEST(acl_backend_dom_to_text, ArtifactIf) +{ stringstream code_out; ArtifactGeneratorCppCode code_gen(code_out); - const char* var_name = "i"; + const char *var_name = "i"; - shared_ptr cond = AF::bin(ArtifactBinOp::lessOrEq, AF::id(var_name), AF::lit("123")); + shared_ptr cond = + AF::bin(ArtifactBinOp::lessOrEq, AF::id(var_name), AF::lit("123")); - shared_ptr expr = AF::bin(ArtifactBinOp::plusAssign, AF::id("hello"), AF::id("world")); + shared_ptr expr = + AF::bin(ArtifactBinOp::plusAssign, AF::id("hello"), AF::id("world")); ArtifactIf if_stmt(cond); @@ -315,13 +321,14 @@ TEST(acl_backend_dom_to_text, ArtifactIf) { ASSERT_EQ(code_out.str(), "if(i <= 123) {\n hello += world;\n}\n"); } -TEST(acl_backend_dom_to_text, ArtifactFunction) { +TEST(acl_backend_dom_to_text, ArtifactFunction) +{ stringstream code_out; stringstream decl_out; ArtifactGeneratorCppCode code_gen(code_out); ArtifactGeneratorCppDecl decl_gen(decl_out); - const char* ret_type = "int"; - const char* func_name = "foo"; + const char *ret_type = "int"; + const char *func_name = "foo"; shared_ptr arg1 = AF::var("int", "a"); shared_ptr arg2 = AF::var("bool", "b"); list> args{arg1, arg2}; @@ -336,14 +343,15 @@ TEST(acl_backend_dom_to_text, ArtifactFunction) { ASSERT_EQ(decl_out.str(), "int foo(int a, bool b);"); } -TEST(acl_backend_dom_to_text, ArtifactClassVariable) { +TEST(acl_backend_dom_to_text, ArtifactClassVariable) +{ stringstream code_out; stringstream decl_out; ArtifactGeneratorCppCode code_gen(code_out); ArtifactGeneratorCppDecl decl_gen(decl_out); - const char* var_type = "int"; - const char* var_name = "data"; + const char *var_type = "int"; + const char *var_name = "data"; ArtifactClass cls("Class"); @@ -360,13 +368,14 @@ TEST(acl_backend_dom_to_text, ArtifactClassVariable) { ASSERT_EQ(decl_out.str(), "int data;\n"); } -TEST(acl_backend_dom_to_text, ArtifactClassFunction) { +TEST(acl_backend_dom_to_text, ArtifactClassFunction) +{ stringstream code_out; stringstream decl_out; ArtifactGeneratorCppCode code_gen(code_out); ArtifactGeneratorCppDecl decl_gen(decl_out); - const char* ret_type = "int"; - const char* func_name = "foo"; + const char *ret_type = "int"; + const char *func_name = "foo"; shared_ptr arg1 = AF::var("int", "a"); shared_ptr arg2 = AF::var("bool", "b"); list> args{arg1, arg2}; @@ -397,10 +406,10 @@ TEST(acl_backend_dom_to_text, ArtifactClassFunction) { ASSERT_EQ(decl_out.str(), "int foo(int a, bool b);\n"); } -static shared_ptr createClsVariable(ArtifactClass& cls, - const char* var_name, - bool is_public) { - const char* var_type = "int"; +static shared_ptr createClsVariable(ArtifactClass &cls, const char *var_name, + bool is_public) +{ + const char *var_type = "int"; shared_ptr dim1 = AF::lit("2"); shared_ptr dim2 = AF::lit("3"); list> dims{dim1, dim2}; @@ -410,11 +419,11 @@ static shared_ptr createClsVariable(ArtifactClass& cls, return var_decl; } -static shared_ptr createClsFunction(ArtifactClass& cls, - const char* func_name, - bool is_public) { - const char* var_type = "int"; - const char* func_type = "void"; +static shared_ptr createClsFunction(ArtifactClass &cls, + const char *func_name, bool is_public) +{ + const char *var_type = "int"; + const char *func_type = "void"; shared_ptr var1 = AF::var(var_type, "a"); shared_ptr var2 = AF::var(var_type, "b"); list> args{var1, var2}; @@ -422,7 +431,8 @@ static shared_ptr createClsFunction(ArtifactClass& cls, return func_decl; } -TEST(acl_backend_dom_to_text, ArtifactClass) { +TEST(acl_backend_dom_to_text, ArtifactClass) +{ stringstream code_out; stringstream decl_out; ArtifactGeneratorCppCode code_gen(code_out); @@ -451,7 +461,8 @@ TEST(acl_backend_dom_to_text, ArtifactClass) { " int invisible;\n};\n"); } -TEST(acl_backend_dom_to_text, ArtifactModule) { +TEST(acl_backend_dom_to_text, ArtifactModule) +{ stringstream code_out; stringstream decl_out; ArtifactGeneratorCppCode code_gen(code_out); @@ -469,16 +480,17 @@ TEST(acl_backend_dom_to_text, ArtifactModule) { // test cpp file generation // We use snippet code to encode some common functions // This snippet is wrapped in prefix and postfix code - const char* code_prefix = "#include \"module.h\"\n\n#include \n\n#include \"bar.h\"\n\n"; - const char* code_suffix = "\nClass::Class() {\n}\n\n"; + const char *code_prefix = "#include \"module.h\"\n\n#include \n\n#include \"bar.h\"\n\n"; + const char *code_suffix = "\nClass::Class() {\n}\n\n"; string ref_data = string(code_prefix) + - string(AclArtifactUtilities, sizeof(AclArtifactUtilities)) + code_suffix; + string(AclArtifactUtilities, sizeof(AclArtifactUtilities)) + code_suffix; m.accept(&code_gen); ASSERT_EQ(code_out.str(), ref_data); // test header code generation - const char* ref_decl_data = "#include \n\n#include \"foo.h\"\n\nclass Class {\npublic:\n Class();\n\nprivate:\n};\n"; + const char *ref_decl_data = "#include \n\n#include \"foo.h\"\n\nclass Class {\npublic:\n " + " Class();\n\nprivate:\n};\n"; m.accept(&decl_gen); ASSERT_EQ(decl_out.str(), ref_decl_data); diff --git a/compiler/nnc/unittests/acl_backend/MIRToDOM.cpp b/compiler/nnc/unittests/acl_backend/MIRToDOM.cpp index 46f329f..e225b14 100644 --- a/compiler/nnc/unittests/acl_backend/MIRToDOM.cpp +++ b/compiler/nnc/unittests/acl_backend/MIRToDOM.cpp @@ -54,28 +54,32 @@ using namespace std; using namespace nnc; using namespace mir; -namespace { +namespace +{ -using OpConstructor = function& inputs)>; +using OpConstructor = function &inputs)>; -const char* artifactName = "nnmodel"; +const char *artifactName = "nnmodel"; /** - * @brief Creates graph with one operation generated by opGen function and returns this operation node + * @brief Creates graph with one operation generated by opGen function and returns this operation + * node * @param g reference to graph which should be filled with operations * @param op_constr functor which creates main operations of graph * @param input_shapes vector of network input shapes * */ -void fillGraph(Graph& g, const OpConstructor& op_constr, const vector& input_shapes) { +void fillGraph(Graph &g, const OpConstructor &op_constr, const vector &input_shapes) +{ // Create graph inputs. - vector inputs; - for (std::size_t i = 0; i < input_shapes.size(); ++i) { + vector inputs; + for (std::size_t i = 0; i < input_shapes.size(); ++i) + { auto input_op = g.create("x" + to_string(i), input_shapes[i]); inputs.push_back(input_op->getOutput(0)); } // Create the operation. - Operation* op = op_constr(g, inputs); + Operation *op = op_constr(g, inputs); // Create graph outputs. for (std::size_t i = 0; i < op->getNumOutputs(); ++i) @@ -89,8 +93,8 @@ void fillGraph(Graph& g, const OpConstructor& op_constr, const vector& in * @param message Message to print in case of check failure */ void checkHeadersSetsEqual(const list &artifact_headers, - const set& expected_headers, - const char* message) { + const set &expected_headers, const char *message) +{ set artifact_set(artifact_headers.begin(), artifact_headers.end()); ASSERT_EQ(artifact_set, expected_headers) << message; } @@ -99,21 +103,21 @@ void checkHeadersSetsEqual(const list &artifact_headers, * @brief Check that artifact DOM has all needed includes * @param m Root module of DOM */ -void checkDomIncludes(const ArtifactModule& m) { +void checkDomIncludes(const ArtifactModule &m) +{ // check system includes, like '#include ' checkHeadersSetsEqual(m.headerSysIncludes(), {"fstream"}, "header includes diverged"); checkHeadersSetsEqual(m.sourceIncludes(), {}, "source includes diverged"); // check ordinary includes, like '#include "artifact_data.h"' - checkHeadersSetsEqual(m.headerIncludes(), {"arm_compute/core/Types.h", - "arm_compute/runtime/BlobLifetimeManager.h", - "arm_compute/runtime/CL/CLBufferAllocator.h", - "arm_compute/runtime/CL/CLFunctions.h", - "arm_compute/runtime/CL/CLScheduler.h", - "arm_compute/runtime/MemoryManagerOnDemand.h", - "arm_compute/runtime/PoolManager.h"}, - "system header includes diverged"); + checkHeadersSetsEqual( + m.headerIncludes(), + {"arm_compute/core/Types.h", "arm_compute/runtime/BlobLifetimeManager.h", + "arm_compute/runtime/CL/CLBufferAllocator.h", "arm_compute/runtime/CL/CLFunctions.h", + "arm_compute/runtime/CL/CLScheduler.h", "arm_compute/runtime/MemoryManagerOnDemand.h", + "arm_compute/runtime/PoolManager.h"}, + "system header includes diverged"); checkHeadersSetsEqual(m.sourceSysIncludes(), {}, "system source includes diverged"); } @@ -123,7 +127,8 @@ void checkDomIncludes(const ArtifactModule& m) { * @param c Main artifact class * @param tensors List of values accessible via getters */ -void checkDomArtifactGetters(const ArtifactClass& c, const vector& tensors) { +void checkDomArtifactGetters(const ArtifactClass &c, const vector &tensors) +{ // TODO } @@ -132,7 +137,8 @@ void checkDomArtifactGetters(const ArtifactClass& c, const vector& tenso * @param c Main artifact class * @param tensors List of NN layers */ -void checkDomArtifactConstructor(const ArtifactClass& c, const vector& tensors) { +void checkDomArtifactConstructor(const ArtifactClass &c, const vector &tensors) +{ // TODO } @@ -141,7 +147,8 @@ void checkDomArtifactConstructor(const ArtifactClass& c, const vector& t * @param f Inference function description * @param layers List of layers in inference */ -void checkDomInference(const ArtifactFunction& f, const vector& layers) { +void checkDomInference(const ArtifactFunction &f, const vector &layers) +{ // TODO } @@ -151,14 +158,16 @@ void checkDomInference(const ArtifactFunction& f, const vector& layers) * @param layers Names of NN layers in inference sequence * @param tensors Names of tensors in artifact */ -void checkArtifactClass(const ArtifactClass& c, - const vector& layers, - const vector& tensors) { +void checkArtifactClass(const ArtifactClass &c, const vector &layers, + const vector &tensors) +{ checkDomArtifactGetters(c, tensors); checkDomArtifactConstructor(c, tensors); - const ArtifactFunction* inf_func = nullptr; - for (const shared_ptr& method: c.publicFunctions()) { - if (method->name() == "Inference") { + const ArtifactFunction *inf_func = nullptr; + for (const shared_ptr &method : c.publicFunctions()) + { + if (method->name() == "Inference") + { inf_func = method.get(); break; } @@ -173,13 +182,13 @@ void checkArtifactClass(const ArtifactClass& c, * @param layers Names of NN layers in inference sequence * @param tensors Names of tensors in artifact */ -void checkDomStructure(const ArtifactModule& m, - const vector& layers, - const vector& tensors) { +void checkDomStructure(const ArtifactModule &m, const vector &layers, + const vector &tensors) +{ ASSERT_EQ(m.name(), artifactName); checkDomIncludes(m); ASSERT_EQ(m.entities().size(), 1); - ArtifactClass* cls = dynamic_cast(m.entities().front().get()); + ArtifactClass *cls = dynamic_cast(m.entities().front().get()); ASSERT_NE(cls, nullptr); checkArtifactClass(*cls, layers, tensors); } @@ -189,27 +198,28 @@ void checkDomStructure(const ArtifactModule& m, * @param shape Desired shape of TV * @return TensorVariant with specified shape */ -TensorVariant createTensorVariant(const Shape& shape) { +TensorVariant createTensorVariant(const Shape &shape) +{ auto num_elems = shape.numElements(); unique_ptr data(new float[num_elems]); - float* data_ptr = data.get(); + float *data_ptr = data.get(); for (int32_t i = 0; i < num_elems; ++i) data_ptr[i] = i; return TensorVariant(DataType::FLOAT32, shape, data_ptr); } - } // Actual tests -TEST(acl_backend_mir_to_dom, constant) { +TEST(acl_backend_mir_to_dom, constant) +{ Shape shape{3, 4}; TensorVariant constant_data = createTensorVariant(shape); Graph g; - OpConstructor op_generator = [&constant_data](Graph& g, - const vector& inputs) { + OpConstructor op_generator = [&constant_data](Graph &g, + const vector &inputs) { return g.create("data", constant_data); }; @@ -218,15 +228,16 @@ TEST(acl_backend_mir_to_dom, constant) { stringstream params_out; AclCppOpGenerator dom_gen(artifactName, params_out); - const ArtifactModule& m = dom_gen.generate(&g); + const ArtifactModule &m = dom_gen.generate(&g); checkDomStructure(m, {}, {}); } -TEST(acl_backend_mir_to_dom, concat) { +TEST(acl_backend_mir_to_dom, concat) +{ Graph g; - OpConstructor op_generator = [](Graph& g, const vector& inputs) { - return g.create("concat", inputs, 3); + OpConstructor op_generator = [](Graph &g, const vector &inputs) { + return g.create("concat", inputs, 3); }; vector input_shapes{{2, 3, 5, 1}, {2, 3, 5, 3}}; @@ -235,7 +246,7 @@ TEST(acl_backend_mir_to_dom, concat) { stringstream params_out; AclCppOpGenerator dom_gen(artifactName, params_out); - const ArtifactModule& m = dom_gen.generate(&g); + const ArtifactModule &m = dom_gen.generate(&g); checkDomStructure(m, {}, {}); @@ -243,23 +254,28 @@ TEST(acl_backend_mir_to_dom, concat) { ArtifactGeneratorCppCode code_gen(code_out); } -TEST(acl_backend_mir_to_dom, DISABLED_add) { +TEST(acl_backend_mir_to_dom, DISABLED_add) +{ // TODO } -TEST(acl_backend_mir_to_dom, DISABLED_mul) { +TEST(acl_backend_mir_to_dom, DISABLED_mul) +{ // TODO } -TEST(acl_backend_mir_to_dom, DISABLED_max) { +TEST(acl_backend_mir_to_dom, DISABLED_max) +{ // TODO } -TEST(acl_backend_mir_to_dom, DISABLED_conv_transposed2d) { +TEST(acl_backend_mir_to_dom, DISABLED_conv_transposed2d) +{ // TODO } -TEST(acl_backend_mir_to_dom, conv2d) { +TEST(acl_backend_mir_to_dom, conv2d) +{ const int32_t channels = 3; mir::Shape kernel_shape{1, 3, 3, channels}; // output Channels, Height, Width, input Channels mir::Shape strides{1, 1}; @@ -267,8 +283,7 @@ TEST(acl_backend_mir_to_dom, conv2d) { Graph g; OpConstructor op_generator = - [kernel_tensor, strides](mir::Graph& g, - const std::vector& inputs) { + [kernel_tensor, strides](mir::Graph &g, const std::vector &inputs) { std::vector padding{0, 0}; auto kernel = g.create("", kernel_tensor)->getOutput(0); return g.create("conv2d", inputs[0], kernel, strides, padding, padding); @@ -281,12 +296,13 @@ TEST(acl_backend_mir_to_dom, conv2d) { stringstream params_out; AclCppOpGenerator dom_gen(artifactName, params_out); - const ArtifactModule& m = dom_gen.generate(&g); + const ArtifactModule &m = dom_gen.generate(&g); checkDomStructure(m, {}, {}); } -TEST(acl_backend_mir_to_dom, depthwise_conv) { +TEST(acl_backend_mir_to_dom, depthwise_conv) +{ const int32_t channels = 3; mir::Shape kernel_shape{3, 3, channels, 1}; // Height, Width, Channels, Channel multiplier mir::Shape strides{1, 1}; @@ -294,12 +310,11 @@ TEST(acl_backend_mir_to_dom, depthwise_conv) { Graph g; OpConstructor op_generator = - [kernel_tensor, strides](mir::Graph& g, - const std::vector& inputs) { + [kernel_tensor, strides](mir::Graph &g, const std::vector &inputs) { std::vector padding{0, 0}; auto kernel = g.create("", kernel_tensor)->getOutput(0); - return g.create("depthwiseConv2d", inputs[0], kernel, - strides, padding, padding); + return g.create("depthwiseConv2d", inputs[0], kernel, strides, + padding, padding); }; vector input_shapes{{1, 10, 10, channels}}; @@ -309,7 +324,7 @@ TEST(acl_backend_mir_to_dom, depthwise_conv) { stringstream params_out; AclCppOpGenerator dom_gen(artifactName, params_out); - const ArtifactModule& m = dom_gen.generate(&g); + const ArtifactModule &m = dom_gen.generate(&g); checkDomStructure(m, {}, {}); @@ -317,7 +332,8 @@ TEST(acl_backend_mir_to_dom, depthwise_conv) { ArtifactGeneratorCppCode code_gen(code_out); } -TEST(acl_backend_mir_to_dom, fully_connected) { +TEST(acl_backend_mir_to_dom, fully_connected) +{ const int32_t in_size = 13; const int32_t out_size = 7; Shape input_shape_data{1, in_size}; @@ -325,7 +341,8 @@ TEST(acl_backend_mir_to_dom, fully_connected) { TensorVariant weights_tensor = createTensorVariant(weights_shape); Graph g; - OpConstructor opGenerator = [weights_tensor](Graph& g, const vector& inputs) { + OpConstructor opGenerator = [weights_tensor](Graph &g, + const vector &inputs) { auto weights = g.create("", weights_tensor)->getOutput(0); return g.create("fc", inputs[0], weights); }; @@ -335,7 +352,7 @@ TEST(acl_backend_mir_to_dom, fully_connected) { stringstream params_out; AclCppOpGenerator dom_gen(artifactName, params_out); - const ArtifactModule& m = dom_gen.generate(&g); + const ArtifactModule &m = dom_gen.generate(&g); checkDomStructure(m, {}, {}); @@ -343,18 +360,19 @@ TEST(acl_backend_mir_to_dom, fully_connected) { ArtifactGeneratorCppCode code_gen(code_out); } -TEST(acl_backend_mir_to_dom, maxpool) { +TEST(acl_backend_mir_to_dom, maxpool) +{ mir::Shape window_shape{3, 3}; // Height, Width mir::Shape strides{1, 1}; Graph g; - OpConstructor op_generator = [window_shape, strides]( - mir::Graph& g, const std::vector& inputs) { - std::vector padding{0, 0}; - return g.create("maxPool", inputs[0], ops::PoolOp::PoolingType::MAX, - window_shape, strides, padding, padding, - mir::ops::PoolOp::BorderType::EMPTY); - }; + OpConstructor op_generator = + [window_shape, strides](mir::Graph &g, const std::vector &inputs) { + std::vector padding{0, 0}; + return g.create("maxPool", inputs[0], ops::PoolOp::PoolingType::MAX, + window_shape, strides, padding, padding, + mir::ops::PoolOp::BorderType::EMPTY); + }; vector input_shapes{{1, 10, 10, 3}}; @@ -363,7 +381,7 @@ TEST(acl_backend_mir_to_dom, maxpool) { stringstream params_out; AclCppOpGenerator dom_gen(artifactName, params_out); - const ArtifactModule& m = dom_gen.generate(&g); + const ArtifactModule &m = dom_gen.generate(&g); checkDomStructure(m, {}, {}); @@ -371,7 +389,8 @@ TEST(acl_backend_mir_to_dom, maxpool) { ArtifactGeneratorCppCode code_gen(code_out); } -TEST(acl_backend_mir_to_dom, DISABLED_avgpool) { +TEST(acl_backend_mir_to_dom, DISABLED_avgpool) +{ // TODO } @@ -379,7 +398,8 @@ TEST(acl_backend_mir_to_dom, DISABLED_avgpool) { * @brief Function to test simple activation operations * @param op_generator functor that generates target operator */ -static void testActivationOp(const OpConstructor& op_generator) { +static void testActivationOp(const OpConstructor &op_generator) +{ Graph g; vector input_shapes{{1, 10, 10, 3}}; @@ -388,7 +408,7 @@ static void testActivationOp(const OpConstructor& op_generator) { stringstream params_out; AclCppOpGenerator dom_gen(artifactName, params_out); - const ArtifactModule& m = dom_gen.generate(&g); + const ArtifactModule &m = dom_gen.generate(&g); checkDomStructure(m, {}, {}); @@ -396,51 +416,58 @@ static void testActivationOp(const OpConstructor& op_generator) { ArtifactGeneratorCppCode code_gen(code_out); } -TEST(acl_backend_mir_to_dom, relu) { - OpConstructor op_generator = [](Graph& g, const std::vector& inputs) { - return g.create("relu", inputs[0]); +TEST(acl_backend_mir_to_dom, relu) +{ + OpConstructor op_generator = [](Graph &g, const std::vector &inputs) { + return g.create("relu", inputs[0]); }; testActivationOp(op_generator); } -TEST(acl_backend_mir_to_dom, capped_relu) { +TEST(acl_backend_mir_to_dom, capped_relu) +{ float cap = 6; - OpConstructor op_generator = [cap](Graph& g, const std::vector& inputs) { - return g.create("capped_relu", inputs[0], cap); + OpConstructor op_generator = [cap](Graph &g, const std::vector &inputs) { + return g.create("capped_relu", inputs[0], cap); }; testActivationOp(op_generator); } -TEST(acl_backend_mir_to_dom, sigmoid) { - OpConstructor op_generator = [](Graph& g, const std::vector& inputs) { - return g.create("sigmoid", inputs[0]); +TEST(acl_backend_mir_to_dom, sigmoid) +{ + OpConstructor op_generator = [](Graph &g, const std::vector &inputs) { + return g.create("sigmoid", inputs[0]); }; testActivationOp(op_generator); } -TEST(acl_backend_mir_to_dom, DISABLED_elu) { +TEST(acl_backend_mir_to_dom, DISABLED_elu) +{ // TODO } -TEST(acl_backend_mir_to_dom, tanh) { - OpConstructor op_generator = [](Graph& g, const std::vector& inputs) { - return g.create("tanh", inputs[0]); +TEST(acl_backend_mir_to_dom, tanh) +{ + OpConstructor op_generator = [](Graph &g, const std::vector &inputs) { + return g.create("tanh", inputs[0]); }; testActivationOp(op_generator); } -TEST(acl_backend_mir_to_dom, DISABLED_reduce_mean) { +TEST(acl_backend_mir_to_dom, DISABLED_reduce_mean) +{ // TODO } -TEST(acl_backend_mir_to_dom, softmax) { +TEST(acl_backend_mir_to_dom, softmax) +{ Graph g; - OpConstructor op_generator = [](Graph& g, const vector& inputs) { - return g.create("softmax", inputs[0], 3); + OpConstructor op_generator = [](Graph &g, const vector &inputs) { + return g.create("softmax", inputs[0], 3); }; vector input_shapes{{1, 1, 1, 3}}; @@ -449,7 +476,7 @@ TEST(acl_backend_mir_to_dom, softmax) { stringstream params_out; AclCppOpGenerator dom_gen(artifactName, params_out); - const ArtifactModule& m = dom_gen.generate(&g); + const ArtifactModule &m = dom_gen.generate(&g); checkDomStructure(m, {}, {}); @@ -457,7 +484,8 @@ TEST(acl_backend_mir_to_dom, softmax) { ArtifactGeneratorCppCode code_gen(code_out); } -TEST(acl_backend_mir_to_dom, reshape) { +TEST(acl_backend_mir_to_dom, reshape) +{ Graph g; const int32_t h = 10; @@ -467,7 +495,7 @@ TEST(acl_backend_mir_to_dom, reshape) { Shape input_shape{1, h, w, c}; Shape output_shape{1, h * w * c}; - OpConstructor op_generator = [output_shape](Graph& g, const vector& inputs) { + OpConstructor op_generator = [output_shape](Graph &g, const vector &inputs) { return g.create("reshape", inputs[0], output_shape); }; @@ -476,7 +504,7 @@ TEST(acl_backend_mir_to_dom, reshape) { stringstream params_out; AclCppOpGenerator dom_gen(artifactName, params_out); - const ArtifactModule& m = dom_gen.generate(&g); + const ArtifactModule &m = dom_gen.generate(&g); checkDomStructure(m, {}, {}); @@ -484,19 +512,21 @@ TEST(acl_backend_mir_to_dom, reshape) { ArtifactGeneratorCppCode code_gen(code_out); } -TEST(acl_backend_mir_to_dom, DISABLED_pad) { +TEST(acl_backend_mir_to_dom, DISABLED_pad) +{ // TODO } -TEST(acl_backend_mir_to_dom, transpose) { +TEST(acl_backend_mir_to_dom, transpose) +{ const int32_t channels = 2; TensorVariant w = createTensorVariant({channels}); vector perm{0, 3, 1, 2}; Graph g; - OpConstructor op_generator = [&perm](Graph& g, const vector& inputs) { - return g.create("transpose", inputs[0], perm); + OpConstructor op_generator = [&perm](Graph &g, const vector &inputs) { + return g.create("transpose", inputs[0], perm); }; vector input_shapes{{1, 10, 10, channels}}; @@ -505,7 +535,7 @@ TEST(acl_backend_mir_to_dom, transpose) { stringstream params_out; AclCppOpGenerator dom_gen(artifactName, params_out); - const ArtifactModule& m = dom_gen.generate(&g); + const ArtifactModule &m = dom_gen.generate(&g); checkDomStructure(m, {}, {}); } diff --git a/compiler/nnc/unittests/caffe2_frontend/test_data/gen_model.py b/compiler/nnc/unittests/caffe2_frontend/test_data/gen_model.py index 697a1a7..52f7997 100755 --- a/compiler/nnc/unittests/caffe2_frontend/test_data/gen_model.py +++ b/compiler/nnc/unittests/caffe2_frontend/test_data/gen_model.py @@ -22,6 +22,6 @@ def save_net(init_net_pb, predict_net_pb, model): resDir = sys.argv[1] m = model_helper.ModelHelper(name='unsupported_net') -m.net.GivenTensorFill([], 'input_data', values=(1.,), shape=(1,)) +m.net.GivenTensorFill([], 'input_data', values=(1., ), shape=(1, )) m.net.Sin(['input_data'], 'result') save_net(os.path.join(resDir, 'init_net.pb'), os.path.join(resDir, 'predict_net.pb'), m) diff --git a/compiler/nnc/unittests/caffe2_frontend/unsupported_caffe2_model.cpp b/compiler/nnc/unittests/caffe2_frontend/unsupported_caffe2_model.cpp index 4a98aed..1982586 100644 --- a/compiler/nnc/unittests/caffe2_frontend/unsupported_caffe2_model.cpp +++ b/compiler/nnc/unittests/caffe2_frontend/unsupported_caffe2_model.cpp @@ -8,16 +8,19 @@ const char *ErrorMsg = "NNC can't load model. Detected problems:\n" " * Sin: unknown layer"; // When adding support for new layers, change the model, not the test -TEST(CAFFE_IMPORT_UNSUPPORTED, ImportAModelWithUnsupportedLayers) { +TEST(CAFFE_IMPORT_UNSUPPORTED, ImportAModelWithUnsupportedLayers) +{ std::string predict_net = std::string(TEST_DIR) + "/predict_net.pb"; std::string init_net = std::string(TEST_DIR) + "/init_net.pb"; nnc::Caffe2ImporterPass importer{predict_net, init_net, {{1}}}; - try { + try + { importer.importModel(); } - catch (nnc::PassException &e) { + catch (nnc::PassException &e) + { ASSERT_EQ(std::string(ErrorMsg), e.what()); importer.cleanup(); return; diff --git a/compiler/nnc/unittests/caffe_frontend/unsupported_caffe_model.cpp b/compiler/nnc/unittests/caffe_frontend/unsupported_caffe_model.cpp index 0e0c387..987397c 100644 --- a/compiler/nnc/unittests/caffe_frontend/unsupported_caffe_model.cpp +++ b/compiler/nnc/unittests/caffe_frontend/unsupported_caffe_model.cpp @@ -4,21 +4,23 @@ #include #include - const char *ErrorMsg = "NNC can't load model. Detected problems:\n" " * DummyData: unsupported layer\n" " * LSTM: parameter 'expose_hidden' has unsupported value: 1\n" " * UnexcitingLayerType: unknown layer"; // When adding support for new layers, change the model, not the test -TEST(CAFFE_IMPORT_UNSUPPORTED, ImportAModelWithUnsupportedLayers) { +TEST(CAFFE_IMPORT_UNSUPPORTED, ImportAModelWithUnsupportedLayers) +{ std::string filename = std::string(TEST_DIR) + "unsupported.caffemodel"; nnc::CaffeImporterPass importer{filename}; - try { + try + { importer.importModel(); } - catch (nnc::PassException &e) { + catch (nnc::PassException &e) + { ASSERT_EQ(std::string(ErrorMsg), e.what()); importer.cleanup(); return; diff --git a/compiler/nnc/unittests/optimizations/CombineTransposes.cpp b/compiler/nnc/unittests/optimizations/CombineTransposes.cpp index 9343213..d0e57b5 100644 --- a/compiler/nnc/unittests/optimizations/CombineTransposes.cpp +++ b/compiler/nnc/unittests/optimizations/CombineTransposes.cpp @@ -25,9 +25,11 @@ using namespace std; using namespace nnc; using namespace mir; -namespace { +namespace +{ -TEST(OptPass, eliminateTransposesLinear) { +TEST(OptPass, eliminateTransposesLinear) +{ mir::Graph g; /* Create graph: * [input] @@ -38,11 +40,11 @@ TEST(OptPass, eliminateTransposesLinear) { * || * [relu] */ - Operation* input = g.create("input", Shape{1, 2, 3}); - Operation* tr1 = g.create("tr", input->getOutput(0), vector{1, 0, 2}); - Operation* tr15 = g.create("tr", tr1->getOutput(0), vector{1, 0, 2}); - Operation* tr2 = g.create("tr", tr15->getOutput(0), vector{1, 0, 2}); - Operation* relu = g.create("relu", tr2->getOutput(0)); + Operation *input = g.create("input", Shape{1, 2, 3}); + Operation *tr1 = g.create("tr", input->getOutput(0), vector{1, 0, 2}); + Operation *tr15 = g.create("tr", tr1->getOutput(0), vector{1, 0, 2}); + Operation *tr2 = g.create("tr", tr15->getOutput(0), vector{1, 0, 2}); + Operation *relu = g.create("relu", tr2->getOutput(0)); // Check that layout is desired std::stringstream ss; @@ -54,7 +56,8 @@ TEST(OptPass, eliminateTransposesLinear) { ASSERT_EQ("i_input.t_tr.r_relu.", ss.str()); } -TEST(OptPass, combineTransposesLinear) { +TEST(OptPass, combineTransposesLinear) +{ mir::Graph g; /* Create graph: * [input] @@ -65,11 +68,10 @@ TEST(OptPass, combineTransposesLinear) { * || * [relu] */ - Operation* input = g.create("input", Shape{1, 2, 3}); - Operation* tr1 = g.create("tr1", input->getOutput(0), - vector{1, 0, 2}); - Operation* tr2 = g.create("tr2", tr1->getOutput(0), vector{0, 2, 1}); - Operation* relu = g.create("relu", tr2->getOutput(0)); + Operation *input = g.create("input", Shape{1, 2, 3}); + Operation *tr1 = g.create("tr1", input->getOutput(0), vector{1, 0, 2}); + Operation *tr2 = g.create("tr2", tr1->getOutput(0), vector{0, 2, 1}); + Operation *relu = g.create("relu", tr2->getOutput(0)); std::stringstream ss; DumpVisitor d(ss); @@ -79,13 +81,15 @@ TEST(OptPass, combineTransposesLinear) { // Assert transposes are combined ASSERT_EQ("i_input.t_tr1new.r_relu.", ss.str()); - auto ax_ord_actual = dynamic_cast( - ( *( g.getInputs()[0]->getOutput(0)->getConsumers().begin()))->getNode())->getAxisOrder(); + auto ax_ord_actual = dynamic_cast( + (*(g.getInputs()[0]->getOutput(0)->getConsumers().begin()))->getNode()) + ->getAxisOrder(); auto ax_ord_true = vector{1, 2, 0}; ASSERT_TRUE(ax_ord_actual == ax_ord_true); } -TEST(OptPass, combineTransposesBush) { +TEST(OptPass, combineTransposesBush) +{ mir::Graph g; /* Create graph: * [input] @@ -96,13 +100,11 @@ TEST(OptPass, combineTransposesBush) { * \\ // * [Add] */ - Operation* input = g.create("input", Shape{1, 2, 3, 2}); - Operation* tr1 = g.create("tr1", input->getOutput(0), - vector{1, 0, 2, 3}); - Operation* tr2 = g.create("tr2", tr1->getOutput(0), - vector{1, 0, 2, 3}); - Operation* tr3 = g.create("tr3", tr1->getOutput(0), - vector{1, 0, 2, 3}); + Operation *input = g.create("input", Shape{1, 2, 3, 2}); + Operation *tr1 = + g.create("tr1", input->getOutput(0), vector{1, 0, 2, 3}); + Operation *tr2 = g.create("tr2", tr1->getOutput(0), vector{1, 0, 2, 3}); + Operation *tr3 = g.create("tr3", tr1->getOutput(0), vector{1, 0, 2, 3}); Operation *elw = g.create("elewiseAdd", tr2->getOutput(0), tr3->getOutput(0)); std::stringstream ss; DumpVisitor d(ss); @@ -114,7 +116,8 @@ TEST(OptPass, combineTransposesBush) { ASSERT_EQ(elw->getInput(1)->getProducer()->getNode()->getName(), "input"); } -TEST(OptPass, combineTransposesOpOrder) { +TEST(OptPass, combineTransposesOpOrder) +{ mir::Graph g; /* Create graph: * [input] [input2] @@ -125,12 +128,12 @@ TEST(OptPass, combineTransposesOpOrder) { * \\ // * [Add] */ - Operation* in1 = g.create("inp1", Shape{1, 2, 3}); - Operation* in2 = g.create("inp2", Shape{1, 2, 3}); - Operation* tr0 = g.create("tr0", in1->getOutput(0), vector{1, 0, 2}); - Operation* tr1 = g.create("tr1", in2->getOutput(0), vector{2, 1, 0}); - Operation* tr2 = g.create("tr2", tr0->getOutput(0), vector{1, 0, 2}); - Operation* tr3 = g.create("tr3", tr1->getOutput(0), vector{2, 1, 0}); + Operation *in1 = g.create("inp1", Shape{1, 2, 3}); + Operation *in2 = g.create("inp2", Shape{1, 2, 3}); + Operation *tr0 = g.create("tr0", in1->getOutput(0), vector{1, 0, 2}); + Operation *tr1 = g.create("tr1", in2->getOutput(0), vector{2, 1, 0}); + Operation *tr2 = g.create("tr2", tr0->getOutput(0), vector{1, 0, 2}); + Operation *tr3 = g.create("tr3", tr1->getOutput(0), vector{2, 1, 0}); Operation *elw = g.create("elewiseAdd", tr2->getOutput(0), tr3->getOutput(0)); g.create("out", elw->getOutput(0)); int n1 = elw->getInput(0)->getNode()->getInput(0)->getNode()->getInput(0)->getNode()->getId(); @@ -138,7 +141,7 @@ TEST(OptPass, combineTransposesOpOrder) { CombineTransposes pass; pass.run(&g); ASSERT_EQ(g.getOutputs()[0]->getInput(0)->getProducer()->getNode()->getName(), "elewiseAdd"); - //Order is preserved + // Order is preserved ASSERT_EQ(n1, elw->getInput(0)->getNode()->getId()); ASSERT_EQ(n2, elw->getInput(1)->getNode()->getId()); } diff --git a/compiler/nnc/unittests/optimizations/FuseArithmeticOps.cpp b/compiler/nnc/unittests/optimizations/FuseArithmeticOps.cpp index e991ce8..da75592 100644 --- a/compiler/nnc/unittests/optimizations/FuseArithmeticOps.cpp +++ b/compiler/nnc/unittests/optimizations/FuseArithmeticOps.cpp @@ -28,9 +28,11 @@ using namespace nnc; using namespace mir; -namespace { +namespace +{ -TEST(OptPass, fuseConvBiasScaleScaleBias) { +TEST(OptPass, fuseConvBiasScaleScaleBias) +{ mir::Graph g; // Create graph: 'input->conv->bias->scale->scale->bias' @@ -38,7 +40,7 @@ TEST(OptPass, fuseConvBiasScaleScaleBias) { auto conv_const = g.create("", TensorVariant(DataType::FLOAT32, {10, 3, 3, 3})); std::vector padding{0, 0}; auto conv = g.create("conv", input->getOutput(0), conv_const->getOutput(0), - Shape{1, 1}, padding, padding); + Shape{1, 1}, padding, padding); auto bias1_const = g.create("", TensorVariant(DataType::FLOAT32, {10})); auto bias1 = g.create("bias1", conv->getOutput(0), bias1_const->getOutput(0)); auto scale1_const = g.create("", TensorVariant(DataType::FLOAT32, {10})); @@ -62,4 +64,4 @@ TEST(OptPass, fuseConvBiasScaleScaleBias) { "const_.const_.i_input.conv_conv.b_bias1." == ss.str()); } -} // unnamed namespace +} // unnamed namespace diff --git a/compiler/nnc/unittests/optimizations/RemoveDeadEnds.cpp b/compiler/nnc/unittests/optimizations/RemoveDeadEnds.cpp index 9f19dbe..c9bc868 100644 --- a/compiler/nnc/unittests/optimizations/RemoveDeadEnds.cpp +++ b/compiler/nnc/unittests/optimizations/RemoveDeadEnds.cpp @@ -14,30 +14,31 @@ * limitations under the License. */ - #include "passes/optimizations/RemoveDeadEnds.h" #include "mir/ops/ReluOp.h" #include "mir/ops/ConstantOp.h" #include -namespace { +namespace +{ using namespace std; using namespace nnc; using namespace mir; -TEST(OptPass, removeDeadEndConstants) { +TEST(OptPass, removeDeadEndConstants) +{ mir::Graph g; /* Create graph: (with useless constants) * [input] * || * [relu] */ - Operation* C0 = g.create("C0", TensorVariant(DataType::FLOAT32, {2, 2})); - Operation* input = g.create("input", Shape{1, 2, 3}); - Operation* C1 = g.create("C1", TensorVariant(DataType::FLOAT32, {2, 2})); - Operation* C2 = g.create("C2", TensorVariant(DataType::FLOAT32, {2, 2})); - Operation* relu = g.create("relu", input->getOutput(0)); + Operation *C0 = g.create("C0", TensorVariant(DataType::FLOAT32, {2, 2})); + Operation *input = g.create("input", Shape{1, 2, 3}); + Operation *C1 = g.create("C1", TensorVariant(DataType::FLOAT32, {2, 2})); + Operation *C2 = g.create("C2", TensorVariant(DataType::FLOAT32, {2, 2})); + Operation *relu = g.create("relu", input->getOutput(0)); std::stringstream ss; RemoveDeadEnds pass; diff --git a/compiler/nnc/unittests/optimizations/SinkTest.cpp b/compiler/nnc/unittests/optimizations/SinkTest.cpp index e75ed33..d20edf2 100644 --- a/compiler/nnc/unittests/optimizations/SinkTest.cpp +++ b/compiler/nnc/unittests/optimizations/SinkTest.cpp @@ -34,19 +34,23 @@ using namespace std; using namespace nnc; using namespace mir; -namespace { -Operation* getPrev(Operation* op) { +namespace +{ +Operation *getPrev(Operation *op) +{ assert(op->getNumInputs() == 1); return op->getInput(0)->getProducer()->getNode(); } -Operation* getNext(Operation* op) { - assert(op->getNumOutputs() == 1 && ( op->getOutput(0)->getConsumers().size() == 1 )); - return ( *op->getOutput(0)->getConsumers().begin())->getNode(); +Operation *getNext(Operation *op) +{ + assert(op->getNumOutputs() == 1 && (op->getOutput(0)->getConsumers().size() == 1)); + return (*op->getOutput(0)->getConsumers().begin())->getNode(); } /* This tests swapping relu and transpose */ -TEST(OptPass, sinkTrReLU) { +TEST(OptPass, sinkTrReLU) +{ mir::Graph g; /* * Create graph: @@ -58,15 +62,14 @@ TEST(OptPass, sinkTrReLU) { * || * [tanh] */ - Operation* input = g.create("input", Shape{1, 2, 3}); - Operation* tr1 = g.create("tr1", input->getOutput(0), - vector{1, 0, 2}); - Operation* relu = g.create("relu", tr1->getOutput(0)); - Operation* tanh = g.create("tanh", relu->getOutput(0)); - Operation* out = g.create("out", tanh->getOutput(0)); - (void) out; - -// Check that layout is desired + Operation *input = g.create("input", Shape{1, 2, 3}); + Operation *tr1 = g.create("tr1", input->getOutput(0), vector{1, 0, 2}); + Operation *relu = g.create("relu", tr1->getOutput(0)); + Operation *tanh = g.create("tanh", relu->getOutput(0)); + Operation *out = g.create("out", tanh->getOutput(0)); + (void)out; + + // Check that layout is desired SinkTranspose pass; pass.run(&g); @@ -78,7 +81,8 @@ TEST(OptPass, sinkTrReLU) { } /* This tests swapping concat and transpose */ -TEST(OptPass, sinkTrConcat) { +TEST(OptPass, sinkTrConcat) +{ mir::Graph g; /* * Create graph: @@ -90,24 +94,21 @@ TEST(OptPass, sinkTrConcat) { * || * [TanH] */ - Operation* in1 = g.create("inp1", Shape{1, 1, 2, 3}); - Operation* in2 = g.create("inp2", Shape{1, 1, 2, 3}); - Operation* tr1 = g.create("tr1", in1->getOutput(0), - vector{0, 3, 1, 2}); - Operation* tr2 = g.create("tr2", in2->getOutput(0), - vector{0, 3, 1, 2}); - Operation* conc = g.create("concat", vector{ - tr1->getOutput(0), tr2->getOutput(0)}, 1); - Operation* tanh = g.create("tanh", conc->getOutput(0)); - Operation* out = g.create("out", tanh->getOutput(0)); - (void) out; + Operation *in1 = g.create("inp1", Shape{1, 1, 2, 3}); + Operation *in2 = g.create("inp2", Shape{1, 1, 2, 3}); + Operation *tr1 = g.create("tr1", in1->getOutput(0), vector{0, 3, 1, 2}); + Operation *tr2 = g.create("tr2", in2->getOutput(0), vector{0, 3, 1, 2}); + Operation *conc = g.create( + "concat", vector{tr1->getOutput(0), tr2->getOutput(0)}, 1); + Operation *tanh = g.create("tanh", conc->getOutput(0)); + Operation *out = g.create("out", tanh->getOutput(0)); + (void)out; // Check that layout is as desired SinkTranspose pass; pass.run(&g); - ASSERT_EQ(getPrev(getPrev(g.getOutputs()[0]))->getType(), - Operation::Type::transpose); - ASSERT_TRUE(static_cast(getPrev(tanh))->getAxisOrder() == + ASSERT_EQ(getPrev(getPrev(g.getOutputs()[0]))->getType(), Operation::Type::transpose); + ASSERT_TRUE(static_cast(getPrev(tanh))->getAxisOrder() == vector({0, 3, 1, 2})); /* Expected Result: * TanH(Transpose(Concat(inp1,inp2))) @@ -115,7 +116,8 @@ TEST(OptPass, sinkTrConcat) { } /* This tests swapping concat and transpose */ -TEST(OptPass, sinkReluConcat) { +TEST(OptPass, sinkReluConcat) +{ mir::Graph g; /* * Create graph: @@ -127,15 +129,15 @@ TEST(OptPass, sinkReluConcat) { * || * [TanH] */ - Operation* in1 = g.create("inp1", Shape{1, 1, 2, 3}); - Operation* in2 = g.create("inp2", Shape{1, 1, 2, 3}); - Operation* relu1 = g.create("relu1", in1->getOutput(0)); - Operation* relu2 = g.create("relu2", in2->getOutput(0)); - Operation* conc = g.create("concat", vector{ - relu1->getOutput(0), relu2->getOutput(0)}, 1); - Operation* tanh = g.create("tanh", conc->getOutput(0)); - Operation* out = g.create("out", tanh->getOutput(0)); - (void) out; + Operation *in1 = g.create("inp1", Shape{1, 1, 2, 3}); + Operation *in2 = g.create("inp2", Shape{1, 1, 2, 3}); + Operation *relu1 = g.create("relu1", in1->getOutput(0)); + Operation *relu2 = g.create("relu2", in2->getOutput(0)); + Operation *conc = g.create( + "concat", vector{relu1->getOutput(0), relu2->getOutput(0)}, 1); + Operation *tanh = g.create("tanh", conc->getOutput(0)); + Operation *out = g.create("out", tanh->getOutput(0)); + (void)out; // Check that layout is as desired SinkRelu pass; @@ -148,7 +150,8 @@ TEST(OptPass, sinkReluConcat) { } /* This tests swapping relu and max_pool */ -TEST(OptPass, sinkPoolReLU) { +TEST(OptPass, sinkPoolReLU) +{ mir::Graph g; /* * Create graph: @@ -160,15 +163,14 @@ TEST(OptPass, sinkPoolReLU) { * || * [tanh] */ - Operation* input = g.create("input", Shape{1, 4, 4, 3}); - Operation* relu = g.create("relu", input->getOutput(0)); - Operation* mp = g.create("pool", relu->getOutput(0), - ops::PoolOp::PoolingType::MAX, Shape{2, 2}, Shape{2, 2}, - vector{0, 0}, vector{0, 0}, - ops::PoolOp::BorderType::EMPTY); - Operation* tanh = g.create("tanh", mp->getOutput(0)); - Operation* out = g.create("out", tanh->getOutput(0)); - (void) out; + Operation *input = g.create("input", Shape{1, 4, 4, 3}); + Operation *relu = g.create("relu", input->getOutput(0)); + Operation *mp = g.create("pool", relu->getOutput(0), ops::PoolOp::PoolingType::MAX, + Shape{2, 2}, Shape{2, 2}, vector{0, 0}, + vector{0, 0}, ops::PoolOp::BorderType::EMPTY); + Operation *tanh = g.create("tanh", mp->getOutput(0)); + Operation *out = g.create("out", tanh->getOutput(0)); + (void)out; SinkRelu pass; pass.run(&g); @@ -180,6 +182,5 @@ TEST(OptPass, sinkPoolReLU) { ASSERT_EQ(getNext(g.getInputs()[0])->getName(), "pool"); ASSERT_EQ(getPrev(g.getOutputs()[0])->getName(), "tanh"); ASSERT_EQ("i_input.p_pool.r_relu.th_tanh.", ss.str()); - } } // unnamed namespace diff --git a/compiler/nnc/unittests/optimizations/Util.h b/compiler/nnc/unittests/optimizations/Util.h index a14bf73..6004702 100644 --- a/compiler/nnc/unittests/optimizations/Util.h +++ b/compiler/nnc/unittests/optimizations/Util.h @@ -28,32 +28,34 @@ #include "mir/ops/Conv2DOp.h" #include "mir/Visitor.h" -namespace nnc { +namespace nnc +{ -class DumpVisitor : public mir::Visitor { +class DumpVisitor : public mir::Visitor +{ public: - explicit DumpVisitor(std::ostream& s) : _s(s) {} + explicit DumpVisitor(std::ostream &s) : _s(s) {} - void visit(mir::ops::InputOp& op) override { _s << "i_" << op.getName() << "."; }; + void visit(mir::ops::InputOp &op) override { _s << "i_" << op.getName() << "."; }; - void visit(mir::ops::TanhOp& op) override { _s << "th_" << op.getName() << "."; } + void visit(mir::ops::TanhOp &op) override { _s << "th_" << op.getName() << "."; } - void visit(mir::ops::MulOp& op) override { _s << "s_" << op.getName() << "."; } + void visit(mir::ops::MulOp &op) override { _s << "s_" << op.getName() << "."; } - void visit(mir::ops::AddOp& op) override { _s << "b_" << op.getName() << "."; } + void visit(mir::ops::AddOp &op) override { _s << "b_" << op.getName() << "."; } - void visit(mir::ops::ReluOp& op) override { _s << "r_" << op.getName() << "."; } + void visit(mir::ops::ReluOp &op) override { _s << "r_" << op.getName() << "."; } - void visit(mir::ops::PoolOp& op) override { _s << "p_" << op.getName() << "."; } + void visit(mir::ops::PoolOp &op) override { _s << "p_" << op.getName() << "."; } - void visit(mir::ops::TransposeOp& op) override { _s << "t_" << op.getName() << "."; } + void visit(mir::ops::TransposeOp &op) override { _s << "t_" << op.getName() << "."; } - void visit(mir::ops::Conv2DOp& op) override { _s << "conv_" << op.getName() << "."; } + void visit(mir::ops::Conv2DOp &op) override { _s << "conv_" << op.getName() << "."; } - void visit(mir::ops::ConstantOp& op) override { _s << "const_" << op.getName() << "."; } + void visit(mir::ops::ConstantOp &op) override { _s << "const_" << op.getName() << "."; } - std::ostream& _s; + std::ostream &_s; }; } // namespace nnc -#endif //NNCC_UTIL_H +#endif // NNCC_UTIL_H diff --git a/compiler/nnc/unittests/pass/PassExceptionTest.cpp b/compiler/nnc/unittests/pass/PassExceptionTest.cpp index e24a640..c55b76f 100644 --- a/compiler/nnc/unittests/pass/PassExceptionTest.cpp +++ b/compiler/nnc/unittests/pass/PassExceptionTest.cpp @@ -20,24 +20,33 @@ using namespace nnc; -namespace { +namespace +{ std::string ErrorMsg = "error constructor"; void passErr1() { throw PassException(ErrorMsg); } -void passErr2() { - try { +void passErr2() +{ + try + { passErr1(); - } catch (const PassException &e) { + } + catch (const PassException &e) + { throw; } } -TEST(CONTRIB_PASS, PassException) { - try { +TEST(CONTRIB_PASS, PassException) +{ + try + { passErr2(); - } catch (const PassException &e) { + } + catch (const PassException &e) + { ASSERT_TRUE(ErrorMsg == e.what()); return; } diff --git a/compiler/nnc/unittests/pass/PassManagerTest.cpp b/compiler/nnc/unittests/pass/PassManagerTest.cpp index f6d734f..952aeed 100644 --- a/compiler/nnc/unittests/pass/PassManagerTest.cpp +++ b/compiler/nnc/unittests/pass/PassManagerTest.cpp @@ -26,7 +26,6 @@ using namespace nnc; - class DummyPass1 : public Pass { public: @@ -34,7 +33,7 @@ public: { auto graph = static_cast(data); - if ( !graph ) + if (!graph) { throw PassException(); } @@ -50,7 +49,7 @@ public: { auto tv = static_cast(data); - if ( !tv ) + if (!tv) { throw PassException(); } diff --git a/compiler/nnc/unittests/soft_backend/CPPHeaderTypes.cpp b/compiler/nnc/unittests/soft_backend/CPPHeaderTypes.cpp index bd81d56..5175966 100644 --- a/compiler/nnc/unittests/soft_backend/CPPHeaderTypes.cpp +++ b/compiler/nnc/unittests/soft_backend/CPPHeaderTypes.cpp @@ -24,23 +24,25 @@ #include "gtest/gtest.h" -template -static inline void checkListShapeEq(List list, Shape shape, index_t volume) { +template static inline void checkListShapeEq(List list, Shape shape, index_t volume) +{ ASSERT_EQ(static_cast(shape.getDims()), list.size()); index_t idx = 0; - for (auto el: list) { + for (auto el : list) + { ASSERT_EQ(shape[idx], el); idx++; } ASSERT_EQ(shape.getNumElems(), volume); } -TEST(SOFT_BACKEND, shape_and_index) { - auto list = {2,3,4}; +TEST(SOFT_BACKEND, shape_and_index) +{ + auto list = {2, 3, 4}; index_t volume = std::accumulate(list.begin(), list.end(), 1, std::multiplies()); Shape s1(list); checkListShapeEq(list, s1, volume); - // This check must be performed only if assertions are enabled +// This check must be performed only if assertions are enabled #ifndef NDEBUG ASSERT_DEATH(s1[list.size()], ""); #endif @@ -48,7 +50,7 @@ TEST(SOFT_BACKEND, shape_and_index) { Shape s2(s1); checkListShapeEq(list, s2, volume); - Shape s3 {1}; + Shape s3{1}; ASSERT_EQ(s3.getNumElems(), 1); ASSERT_EQ(s3.getDims(), 1); s3 = s1; @@ -56,12 +58,13 @@ TEST(SOFT_BACKEND, shape_and_index) { s3.setDims(4); s3[3] = 2; - ASSERT_EQ(s3.getNumElems(), volume*2); + ASSERT_EQ(s3.getNumElems(), volume * 2); s3.setDims(3); ASSERT_EQ(s3.getNumElems(), volume); } -TEST(SOFT_BACKEND, tensor) { +TEST(SOFT_BACKEND, tensor) +{ // test reshape Tensor t1; ASSERT_EQ(t1.getShape().getNumElems(), 1); @@ -72,14 +75,16 @@ TEST(SOFT_BACKEND, tensor) { // test at functions float expected_sum = 0; for (index_t i = 0; i < tensor1_height; ++i) - for (index_t j = 0; j < tensor1_width; ++j) { + for (index_t j = 0; j < tensor1_width; ++j) + { index_t elem = (i + 1) * (j + 1); expected_sum += elem; t1.at({i, j}) = elem; } float sum = 0; for (index_t i = 0; i < tensor1_height; ++i) - for (index_t j = 0; j < tensor1_width; ++j) { + for (index_t j = 0; j < tensor1_width; ++j) + { sum += t1.at({i, j}); } ASSERT_EQ(sum, expected_sum); @@ -96,13 +101,14 @@ TEST(SOFT_BACKEND, tensor) { const index_t tensor3_width = 3; std::vector data({1.0, 2.0, 4.0}); data.resize(tensor3_depth * tensor3_height * tensor3_width); - float* data_ptr = data.data(); + float *data_ptr = data.data(); Tensor t3(Shape({tensor3_depth, tensor3_height, tensor3_width}), data_ptr); ASSERT_EQ(t3.getShape().getNumElems(), tensor3_depth * tensor3_height * tensor3_width); sum = 0; for (index_t k = 0; k < tensor3_depth; ++k) for (index_t i = 0; i < tensor3_height; ++i) - for (index_t j = 0; j < tensor3_width; ++j) { + for (index_t j = 0; j < tensor3_width; ++j) + { sum += t3.at({k, i, j}); } ASSERT_EQ(sum, std::accumulate(data_ptr, data_ptr + t3.getShape().getNumElems(), 0.0f)); @@ -113,7 +119,8 @@ TEST(SOFT_BACKEND, tensor) { t4 = t3; for (index_t k = 0; k < tensor3_depth; ++k) for (index_t i = 0; i < tensor3_height; ++i) - for (index_t j = 0; j < tensor3_height; ++j) { + for (index_t j = 0; j < tensor3_height; ++j) + { ASSERT_EQ(t3.at({k, i, j}), t4.at({k, i, j})); } } diff --git a/compiler/nnc/unittests/soft_backend/CPPOperations.cpp b/compiler/nnc/unittests/soft_backend/CPPOperations.cpp index a907332..0fc9eca 100644 --- a/compiler/nnc/unittests/soft_backend/CPPOperations.cpp +++ b/compiler/nnc/unittests/soft_backend/CPPOperations.cpp @@ -112,26 +112,30 @@ namespace irOps = mir::ops; NNC data types are: mir::TensorVariant, tensor::Shape, mir::Tensor */ -namespace { +namespace +{ /** - * @brief Creates graph with one operation generated by opGen function and returns this operation node + * @brief Creates graph with one operation generated by opGen function and returns this operation + * node */ -mir::Operation* -fillGraph(mir::Graph& g, - const function& inputs)>& op_gen, - const vector>& input_ntensors) { +mir::Operation * +fillGraph(mir::Graph &g, + const function &inputs)> + &op_gen, + const vector> &input_ntensors) +{ // Create graph inputs. - std::vector inputs; - for (std::size_t i = 0; i < input_ntensors.size(); ++i) { + std::vector inputs; + for (std::size_t i = 0; i < input_ntensors.size(); ++i) + { auto input_op = g.create("x" + std::to_string(i), input_ntensors[i]->getShape()); inputs.push_back(input_op->getOutput(0)); } // Create the operation. - mir::Operation* op = op_gen(g, inputs); + mir::Operation *op = op_gen(g, inputs); // Create graph outputs. assert(op->getNumOutputs() == 1); @@ -144,7 +148,8 @@ fillGraph(mir::Graph& g, /** * @brief Fills NNC Shape object with data from src container */ -void fillNShape(mir::Shape &nshape, const vector &raw_shape_data) { +void fillNShape(mir::Shape &nshape, const vector &raw_shape_data) +{ int shape_rank = raw_shape_data.size(); nshape.resize(shape_rank); for (int i = 0; i < shape_rank; ++i) @@ -154,7 +159,8 @@ void fillNShape(mir::Shape &nshape, const vector &raw_shape_data) { /** * @brief Converts NNC Shape to artifact Shape */ -void copyAShapeFromNShape(Shape &ashape, const mir::Shape &src) { +void copyAShapeFromNShape(Shape &ashape, const mir::Shape &src) +{ int shape_rank = src.rank(); ashape.setDims(shape_rank); for (int i = 0; i < shape_rank; ++i) @@ -164,7 +170,8 @@ void copyAShapeFromNShape(Shape &ashape, const mir::Shape &src) { /** * @brief Fills NNC and artifact Shape objects with data from rawShapeData */ -void fillShapes(mir::Shape &nshape, Shape &ashape, const vector &raw_shape_data) { +void fillShapes(mir::Shape &nshape, Shape &ashape, const vector &raw_shape_data) +{ fillNShape(nshape, raw_shape_data); copyAShapeFromNShape(ashape, nshape); } @@ -172,10 +179,12 @@ void fillShapes(mir::Shape &nshape, Shape &ashape, const vector &raw_shape_ /** * @brief Fills NNC tensor with some determined data */ -void fillNTensor(mir::TensorVariant &dst, float start) { +void fillNTensor(mir::TensorVariant &dst, float start) +{ float t = start; mir::Tensor wrapper(dst); - for (const mir::Index& idx: mir::ShapeRange(dst.getShape())) { + for (const mir::Index &idx : mir::ShapeRange(dst.getShape())) + { wrapper.at(idx) = sin(t) * 2.0f; t += 1.0f; } @@ -184,12 +193,14 @@ void fillNTensor(mir::TensorVariant &dst, float start) { /** * @brief Converts NNC mir::TensorVariant to artifact Tensor object */ -void copyATensorFromNTensor(Tensor &dst, mir::TensorVariant &src) { +void copyATensorFromNTensor(Tensor &dst, mir::TensorVariant &src) +{ mir::Tensor wrapper(src); Index art_idx; int rank = src.getShape().rank(); art_idx.setDims(rank); - for (mir::Index idx: mir::ShapeRange(src.getShape())) { + for (mir::Index idx : mir::ShapeRange(src.getShape())) + { for (int i = 0; i < rank; ++i) art_idx[i] = idx.at(i); dst.at(art_idx) = wrapper.at(idx); @@ -199,10 +210,9 @@ void copyATensorFromNTensor(Tensor &dst, mir::TensorVariant &src) { /** * @brief Fills NNC and artifact tensor objects with some determined data */ -void fillTensors(unique_ptr &ntensor, - Tensor &atensor, - const vector &shape, - float start) { +void fillTensors(unique_ptr &ntensor, Tensor &atensor, const vector &shape, + float start) +{ Shape ashape; mir::Shape nshape; fillShapes(nshape, ashape, shape); @@ -215,22 +225,23 @@ void fillTensors(unique_ptr &ntensor, /** * @brief Run interpreter to get reference output data */ -mir::TensorVariant -getReferenceTensor(mir::Graph& g, - const vector>& input_ntensors) { +mir::TensorVariant getReferenceTensor(mir::Graph &g, + const vector> &input_ntensors) +{ NNInterpreter interpreter; for (int i = 0; i < static_cast(input_ntensors.size()); ++i) interpreter.setInput("x" + to_string(i), *input_ntensors[i]); g.accept(&interpreter); - const auto* output_op = g.getOutputs()[0]; + const auto *output_op = g.getOutputs()[0]; return interpreter.getResult(output_op->getInput(0)->getProducer()); }; /** - * @brief Run selected operation, used to make code in tests more compact and fit getReferenceTensor format + * @brief Run selected operation, used to make code in tests more compact and fit getReferenceTensor + * format */ -template -Tensor run(Operation op, const Args &...args) { +template Tensor run(Operation op, const Args &... args) +{ Tensor output; op(output, args...); return output; @@ -242,9 +253,11 @@ Tensor run(Operation op, const Args &...args) { * @param b Second number to compare * @param ulp Max tolerated number of units in the last place * @param eps Max tolerated absolute difference - * @return true if diff of two numbers is less than 'eps' or ULP between arguments is less than 'ulp' + * @return true if diff of two numbers is less than 'eps' or ULP between arguments is less than + * 'ulp' */ -bool areFloatsNear(float a, float b, int32_t ulp, float eps) { +bool areFloatsNear(float a, float b, int32_t ulp, float eps) +{ assert(ulp < (1 << 23) && "this algorithm is not applicable for such large diffs"); assert(eps >= 0 && "epsilon should be positive number"); if (fabs(a - b) <= eps) @@ -266,7 +279,8 @@ bool areFloatsNear(float a, float b, int32_t ulp, float eps) { * @param ref_nnc_tensor Reference tensor that interpreter produced * @param test_art_tensor Tensor that artifact operation computed */ -void compareResults(const mir::TensorVariant &ref_nnc_tensor, const Tensor &test_art_tensor) { +void compareResults(const mir::TensorVariant &ref_nnc_tensor, const Tensor &test_art_tensor) +{ assert(ref_nnc_tensor.getElementSize() == 4L && ref_nnc_tensor.getDataType() == mir::DataType::FLOAT32); @@ -283,7 +297,8 @@ void compareResults(const mir::TensorVariant &ref_nnc_tensor, const Tensor &test // check that reference and test tensor contents are equal Index artifact_idx; artifact_idx.setDims(rank); - for (mir::Index nnc_idx: mir::ShapeRange(nnc_shape)) { + for (mir::Index nnc_idx : mir::ShapeRange(nnc_shape)) + { for (int i = 0; i < rank; ++i) artifact_idx[i] = nnc_idx.at(i); // Input and output data lies in range of [-10, 10], @@ -291,21 +306,22 @@ void compareResults(const mir::TensorVariant &ref_nnc_tensor, const Tensor &test float ref_data = mir::Tensor(ref_nnc_tensor).at(nnc_idx); float test_data = test_art_tensor.at(artifact_idx); ASSERT_TRUE(areFloatsNear(ref_data, test_data, 32, 1e-5)) - << "Tensor element " << nnc_idx << " diverged, reference: " - << ref_data << " test result: " << test_data; + << "Tensor element " << nnc_idx << " diverged, reference: " << ref_data + << " test result: " << test_data; } } /** - * @brief This function creates test graph, runs interpeter, specifies artifact operation and compares results + * @brief This function creates test graph, runs interpeter, specifies artifact operation and + * compares results */ -template +template void createAndRunTestGraph( - function& inputs)> op_generator, - TestFunc artifactOperation, - const vector>& input_ntensors, - Args& ...input_atensors) { + function &inputs)> + op_generator, + TestFunc artifactOperation, const vector> &input_ntensors, + Args &... input_atensors) +{ mir::Graph g; mir::Operation *actual_operation = fillGraph(g, op_generator, input_ntensors); @@ -316,7 +332,7 @@ void createAndRunTestGraph( inference_sequence.push_back(std::move(op_call)); Serializer serializer; serializer.serialize(inference_sequence); - assert(static_cast(inference_sequence.front().get())->paramStartOffset == 0); + assert(static_cast(inference_sequence.front().get())->paramStartOffset == 0); mir::TensorVariant reference_output = getReferenceTensor(g, input_ntensors); @@ -325,10 +341,10 @@ void createAndRunTestGraph( compareResults(reference_output, test_output); } - } -TEST(cpp_operations_test, capped_relu) { +TEST(cpp_operations_test, capped_relu) +{ // test prerequisites // cap has this value to cut input numbers(they are in range [-1, 1]) float cap = 0.5f; @@ -336,14 +352,15 @@ TEST(cpp_operations_test, capped_relu) { Tensor input_atensor; vector> input_ntensors(1); fillTensors(input_ntensors[0], input_atensor, shape_data, 1.0f); - auto op_generator = [cap](mir::Graph& g, const std::vector& inputs) { + auto op_generator = [cap](mir::Graph &g, const std::vector &inputs) { return g.create("y", inputs[0], cap); }; createAndRunTestGraph(op_generator, cappedRelu, input_ntensors, input_atensor); } -TEST(cpp_operations_test, concat) { +TEST(cpp_operations_test, concat) +{ for (int num_dims = 1; num_dims <= 4; ++num_dims) for (int axis = 0; axis < num_dims; ++axis) { @@ -358,15 +375,12 @@ TEST(cpp_operations_test, concat) { vector> input_ntensors(2); fillTensors(input_ntensors[0], input_atensors[0], shape_data1, 1.0f); fillTensors(input_ntensors[1], input_atensors[1], shape_data2, 2.0f); - auto op_generator = [axis](mir::Graph& g, - const std::vector& inputs) { + auto op_generator = [axis](mir::Graph &g, + const std::vector &inputs) { return g.create("y", inputs, axis); }; - createAndRunTestGraph(op_generator, - concat, - input_ntensors, - input_atensors[0], + createAndRunTestGraph(op_generator, concat, input_ntensors, input_atensors[0], input_atensors[1]); } } @@ -517,11 +531,13 @@ TEST(cpp_operations_test, max) } } -TEST(cpp_operations_test, convTransposed2d) { +TEST(cpp_operations_test, convTransposed2d) +{ // Iterate over kernel width, kernel height, // input channels(input_c), output channels(output_c), // stride width, stride height - // size 3 is chosen to cover all cases, where width bigger/smaller then height and equal/not equal to 1 + // size 3 is chosen to cover all cases, where width bigger/smaller then height and equal/not equal + // to 1 using iT = int32_t; Tensor temporary(Shape({1024 * 40})); for (iT kernel_h = 2; kernel_h <= 4; ++kernel_h) @@ -529,8 +545,9 @@ TEST(cpp_operations_test, convTransposed2d) { for (iT input_c = 1; input_c <= 3; ++input_c) for (iT output_c = 1; output_c <= 3; ++output_c) for (iT stride_h = 1; stride_h <= 3; ++stride_h) - for (iT stride_w = 1; stride_w <= 3; ++stride_w) { - vector input_shape_data{3, 9, 3, static_cast(input_c)}; // NHWC + for (iT stride_w = 1; stride_w <= 3; ++stride_w) + { + vector input_shape_data{3, 9, 3, static_cast(input_c)}; // NHWC vector kernel_shape_data{kernel_h, kernel_w, output_c, input_c}; mir::Shape strides{stride_h, stride_w}; vector> input_ntensors(2); @@ -540,20 +557,22 @@ TEST(cpp_operations_test, convTransposed2d) { fillTensors(input_ntensors[1], input_atensor1, kernel_shape_data, 1.0f); auto pad_t = mir::ops::PaddingType::Same; auto op_generator = [&strides, pad_t]( - mir::Graph& g, const std::vector& inputs) { + mir::Graph &g, const std::vector &inputs) { return g.create("y", inputs[0], inputs[1], strides, pad_t); }; - createAndRunTestGraph(op_generator, convTransposed2d, input_ntensors, - input_atensor0, input_atensor1, temporary); + createAndRunTestGraph(op_generator, convTransposed2d, input_ntensors, input_atensor0, + input_atensor1, temporary); } } -TEST(cpp_operations_test, conv2d) { +TEST(cpp_operations_test, conv2d) +{ // Iterate over kernel width, kernel height, // input channels(input_c), output channels(output_c), // stride width, stride height - // size 3 is chosen to cover all cases, where width bigger/smaller then height and equal/not equal to 1 + // size 3 is chosen to cover all cases, where width bigger/smaller then height and equal/not equal + // to 1 using iT = int32_t; Tensor temporary(Shape({1024 * 20})); for (iT kernel_h = 1; kernel_h <= 3; ++kernel_h) @@ -561,8 +580,9 @@ TEST(cpp_operations_test, conv2d) { for (iT input_c = 1; input_c <= 3; ++input_c) for (iT output_c = 1; output_c <= 3; ++output_c) for (iT stride_h = 1; stride_h <= 3; ++stride_h) - for (iT stride_w = 1; stride_w <= 3; ++stride_w) { - vector input_shape_data{3, 5, 7, static_cast(input_c)}; // NHWC + for (iT stride_w = 1; stride_w <= 3; ++stride_w) + { + vector input_shape_data{3, 5, 7, static_cast(input_c)}; // NHWC vector kernel_shape_data{output_c, kernel_h, kernel_w, input_c}; // OHWI mir::Shape strides{stride_h, stride_w}; vector> input_ntensors(2); @@ -570,32 +590,35 @@ TEST(cpp_operations_test, conv2d) { Tensor input_atensor1; fillTensors(input_ntensors[0], input_atensor0, input_shape_data, 1.0f); fillTensors(input_ntensors[1], input_atensor1, kernel_shape_data, 1.0f); - auto op_generator = [&strides](mir::Graph& g, - const std::vector& inputs) { + auto op_generator = [&strides](mir::Graph &g, + const std::vector &inputs) { std::vector padding{0, 0}; - return g.create("y", inputs[0], inputs[1], - strides, padding, padding); + return g.create("y", inputs[0], inputs[1], strides, padding, + padding); }; - createAndRunTestGraph(op_generator, conv2d, input_ntensors, - input_atensor0, input_atensor1, temporary); + createAndRunTestGraph(op_generator, conv2d, input_ntensors, input_atensor0, + input_atensor1, temporary); } } -TEST(cpp_operations_test, depthwise_conv) { +TEST(cpp_operations_test, depthwise_conv) +{ // Iterate over kernel width, kernel height, // channels // stride width, stride height // layers multiplier - // size 3 is chosen to cover all cases, where width bigger/smaller then height and equal/not equal to 1 + // size 3 is chosen to cover all cases, where width bigger/smaller then height and equal/not equal + // to 1 using iT = int32_t; for (iT kernel_h = 1; kernel_h <= 3; ++kernel_h) for (iT kernel_w = 1; kernel_w <= 3; ++kernel_w) for (iT channels = 1; channels <= 3; ++channels) for (iT stride_w = 1; stride_w <= 3; ++stride_w) for (iT stride_h = 1; stride_h <= 3; ++stride_h) - for (iT multiplier = 1; multiplier <= 2; ++multiplier) { - vector input_shape_data{3, 7, 6, static_cast(channels)}; // NHWC + for (iT multiplier = 1; multiplier <= 2; ++multiplier) + { + vector input_shape_data{3, 7, 6, static_cast(channels)}; // NHWC vector kernel_shape_data{kernel_h, kernel_w, channels, multiplier}; // HWCN mir::Shape strides{stride_h, stride_w}; vector> input_ntensors(2); @@ -603,19 +626,20 @@ TEST(cpp_operations_test, depthwise_conv) { Tensor input_atensor1; fillTensors(input_ntensors[0], input_atensor0, input_shape_data, 1.0f); fillTensors(input_ntensors[1], input_atensor1, kernel_shape_data, 1.0f); - auto op_generator = [&strides](mir::Graph& g, - const std::vector& inputs) { + auto op_generator = [&strides](mir::Graph &g, + const std::vector &inputs) { std::vector padding{0, 0}; - return g.create("y", inputs[0], inputs[1], - strides, padding, padding); + return g.create("y", inputs[0], inputs[1], strides, + padding, padding); }; - createAndRunTestGraph(op_generator, depthwiseConv2d, input_ntensors, - input_atensor0, input_atensor1); + createAndRunTestGraph(op_generator, depthwiseConv2d, input_ntensors, input_atensor0, + input_atensor1); } } -TEST(cpp_operations_test, fully_connected) { +TEST(cpp_operations_test, fully_connected) +{ vector input_shape_data{3, 13}; vector weights_shape_data{13, 7}; vector> input_ntensors(2); @@ -623,86 +647,78 @@ TEST(cpp_operations_test, fully_connected) { Tensor input_atensor1; fillTensors(input_ntensors[0], input_atensor0, input_shape_data, 1.0f); fillTensors(input_ntensors[1], input_atensor1, weights_shape_data, 1.0f); - auto op_generator = [](mir::Graph& g, const std::vector& inputs) { + auto op_generator = [](mir::Graph &g, const std::vector &inputs) { return g.create("y", inputs[0], inputs[1]); }; createAndRunTestGraph(op_generator, fullConnect, input_ntensors, input_atensor0, input_atensor1); } -TEST(cpp_operations_test, resize_NN_test) { - mir::Shape test_shapes[] = { - {1, 8, 8, 1}, - {2, 10, 10, 1}, - {1, 11, 11, 2}, - {2, 8, 12, 2}, - {1, 48, 12, 1}, - {1, 48, 48, 1}, - {1, 48, 56, 1} - }; - for (mir::Shape res_shape: test_shapes) { +TEST(cpp_operations_test, resize_NN_test) +{ + mir::Shape test_shapes[] = {{1, 8, 8, 1}, {2, 10, 10, 1}, {1, 11, 11, 2}, {2, 8, 12, 2}, + {1, 48, 12, 1}, {1, 48, 48, 1}, {1, 48, 56, 1}}; + for (mir::Shape res_shape : test_shapes) + { vector input_shape_data{res_shape.dim(0), 4, 4, res_shape.dim(3)}; vector> input_ntensors(1); Tensor input_atensor; fillTensors(input_ntensors[0], input_atensor, input_shape_data, 1.0f); - auto op_generator = [&res_shape](mir::Graph& g, - const std::vector& inputs) { + auto op_generator = [&res_shape](mir::Graph &g, + const std::vector &inputs) { return g.create( - "y", inputs[0], - mir::ops::ResizeOp::ResizeMethod::nearestNeighbor, res_shape); + "y", inputs[0], mir::ops::ResizeOp::ResizeMethod::nearestNeighbor, res_shape); }; createAndRunTestGraph(op_generator, resize, input_ntensors, input_atensor); } } -TEST(cpp_operations_test, resize_NN_test_scales) { +TEST(cpp_operations_test, resize_NN_test_scales) +{ cout << "\n"; std::vector test_scales[] = { - {1, 2, 2, 1}, - {1, 2, 3, 1}, - {1, 3, 2, 1}, - {1, 2.5, 2, 1}, - {1, 3, 9, 1} - }; - for (const std::vector& scales: test_scales) { + {1, 2, 2, 1}, {1, 2, 3, 1}, {1, 3, 2, 1}, {1, 2.5, 2, 1}, {1, 3, 9, 1}}; + for (const std::vector &scales : test_scales) + { vector input_shape_data{1, 4, 4, 1}; vector> input_ntensors(1); Tensor input_atensor; fillTensors(input_ntensors[0], input_atensor, input_shape_data, 1.0f); - auto op_generator = [&scales](mir::Graph& g, - const std::vector& inputs) { + auto op_generator = [&scales](mir::Graph &g, + const std::vector &inputs) { return g.create( - "y", inputs[0], - mir::ops::ResizeOp::ResizeMethod::nearestNeighbor, scales); + "y", inputs[0], mir::ops::ResizeOp::ResizeMethod::nearestNeighbor, scales); }; createAndRunTestGraph(op_generator, resize, input_ntensors, input_atensor); } } template -static mir::Operation* createPool(mir::Graph& g, - const std::vector& inputs, - mir::Shape& window_shape, - mir::Shape& strides, - irOps::PoolOp::BorderType border) { +static mir::Operation * +createPool(mir::Graph &g, const std::vector &inputs, + mir::Shape &window_shape, mir::Shape &strides, irOps::PoolOp::BorderType border) +{ std::vector padding{0, 0}; - return g.create("pool", inputs[0], poolT, window_shape, strides, - padding, padding, border); + return g.create("pool", inputs[0], poolT, window_shape, strides, padding, + padding, border); }; template -static void genericPoolTest(Func test_func, const vector borders) { +static void genericPoolTest(Func test_func, const vector borders) +{ // Iterate over window width, window height // channels // stride width, stride height - // size 3 is chosen to cover all cases, where width bigger/smaller then height and equal/not equal to 1 + // size 3 is chosen to cover all cases, where width bigger/smaller then height and equal/not equal + // to 1 using iT = int32_t; for (iT windowH = 1; windowH <= 3; ++windowH) for (iT windowW = 1; windowW <= 3; ++windowW) for (iT channels = 1; channels <= 2; ++channels) for (iT stride_h = 1; stride_h <= 3; ++stride_h) - for (iT stride_w = 1; stride_w <= 3; ++stride_w) { + for (iT stride_w = 1; stride_w <= 3; ++stride_w) + { vector shape_data{3, 5, 7, static_cast(channels)}; mir::Shape window_shape{windowH, windowW}; mir::Shape strides{stride_h, stride_w}; @@ -710,7 +726,8 @@ static void genericPoolTest(Func test_func, const vector> input_ntensors(1); fillTensors(input_ntensors[0], input_atensor, shape_data, 1.0f); - for (auto border: borders) { + for (auto border : borders) + { using namespace std::placeholders; auto op_generator = @@ -721,109 +738,106 @@ static void genericPoolTest(Func test_func, const vector border_types = { - irOps::PoolOp::BorderType::EMPTY - }; +TEST(cpp_operations_test, maxpool) +{ + vector border_types = {irOps::PoolOp::BorderType::EMPTY}; genericPoolTest(maxPool, border_types); } -TEST(cpp_operations_test, avgpool) { - vector border_types = { - irOps::PoolOp::BorderType::EMPTY, - irOps::PoolOp::BorderType::ZEROFILLED - }; +TEST(cpp_operations_test, avgpool) +{ + vector border_types = {irOps::PoolOp::BorderType::EMPTY, + irOps::PoolOp::BorderType::ZEROFILLED}; genericPoolTest(avgPool, border_types); } -TEST(cpp_operations_test, relu) { +TEST(cpp_operations_test, relu) +{ // test prerequisites vector shape_data{2, 3, 4, 5}; Tensor input_atensor; vector> input_ntensors(1); fillTensors(input_ntensors[0], input_atensor, shape_data, 1.0f); - auto op_generator = [](mir::Graph& g, const std::vector& inputs) { + auto op_generator = [](mir::Graph &g, const std::vector &inputs) { return g.create("y", inputs[0]); }; createAndRunTestGraph(op_generator, relu, input_ntensors, input_atensor); } -TEST(cpp_operations_test, leaky_relu) { +TEST(cpp_operations_test, leaky_relu) +{ // test prerequisites vector shape_data{2, 3, 4, 5}; Tensor input_atensor; vector> input_ntensors(1); fillTensors(input_ntensors[0], input_atensor, shape_data, 1.0f); - auto op_generator = [](mir::Graph& g, const std::vector& inputs) { + auto op_generator = [](mir::Graph &g, const std::vector &inputs) { return g.create("y", inputs[0], 0.1); }; createAndRunTestGraph(op_generator, leakyRelu, input_ntensors, input_atensor); } -TEST(cpp_operations_test, sigmoid) { +TEST(cpp_operations_test, sigmoid) +{ // test prerequisites vector shape_data{2, 3, 4, 5}; Tensor input_atensor; vector> input_ntensors(1); fillTensors(input_ntensors[0], input_atensor, shape_data, 1.0f); - auto opGenerator = [](mir::Graph& g, const std::vector& inputs) { + auto opGenerator = [](mir::Graph &g, const std::vector &inputs) { return g.create("y", inputs[0]); }; createAndRunTestGraph(opGenerator, sigmoid, input_ntensors, input_atensor); } -TEST(cpp_operations_test, elu) { +TEST(cpp_operations_test, elu) +{ // test prerequisites vector shape_data{2, 3, 4, 5}; Tensor input_atensor; vector> input_ntensors(1); fillTensors(input_ntensors[0], input_atensor, shape_data, 1.0f); - auto op_generator = [](mir::Graph& g, const std::vector& inputs) { + auto op_generator = [](mir::Graph &g, const std::vector &inputs) { return g.create("y", inputs[0], 1); }; createAndRunTestGraph(op_generator, elu, input_ntensors, input_atensor); } -TEST(cpp_operations_test, tanh) { +TEST(cpp_operations_test, tanh) +{ // test prerequisites vector shape_data{2, 3, 4, 5}; Tensor input_atensor; vector> input_ntensors(1); fillTensors(input_ntensors[0], input_atensor, shape_data, 1.0f); - auto op_generator = [](mir::Graph& g, const std::vector& inputs) { + auto op_generator = [](mir::Graph &g, const std::vector &inputs) { return g.create("y", inputs[0]); }; createAndRunTestGraph(op_generator, tanhActivation, input_ntensors, input_atensor); } -TEST(cpp_operations_test, reduceMeanTst) { +TEST(cpp_operations_test, reduceMeanTst) +{ // test prerequisites // different test cases - std::vector test_axis_list[] = { - {2, 3}, - {1}, - {0}, - {2}, - {3}, - {0, 2}, - {1, 2, 3} - }; - for (const vector& axis_list: test_axis_list) { - for (const bool keep_dims: {true, false}) { + std::vector test_axis_list[] = {{2, 3}, {1}, {0}, {2}, {3}, {0, 2}, {1, 2, 3}}; + for (const vector &axis_list : test_axis_list) + { + for (const bool keep_dims : {true, false}) + { vector input_shape_data{2, 3, 4, 5}; Tensor input_atensor; vector> input_ntensors(1); fillTensors(input_ntensors[0], input_atensor, input_shape_data, 1.0f); auto op_generator = [&axis_list, keep_dims]( - mir::Graph& g, const std::vector& inputs) { - auto op = g.create( - "y", inputs[0], axis_list, keep_dims, - mir::ops::ReduceOp::FuncType::mean); + mir::Graph &g, const std::vector &inputs) { + auto op = g.create("y", inputs[0], axis_list, keep_dims, + mir::ops::ReduceOp::FuncType::mean); return op; }; @@ -832,9 +846,11 @@ TEST(cpp_operations_test, reduceMeanTst) { } } -TEST(cpp_operations_test, softmax) { +TEST(cpp_operations_test, softmax) +{ // iterate over number of dimensions in tensor - for (int num_dims = 1; num_dims <= 4; ++num_dims) { + for (int num_dims = 1; num_dims <= 4; ++num_dims) + { // test prerequisites vector shape_data{2, 3, 4, 5}; shape_data.resize(num_dims); @@ -842,7 +858,7 @@ TEST(cpp_operations_test, softmax) { Tensor input_atensor; vector> input_ntensors(1); fillTensors(input_ntensors[0], input_atensor, shape_data, 1.0f); - auto op_generator = [axis](mir::Graph& g, const std::vector& inputs) { + auto op_generator = [axis](mir::Graph &g, const std::vector &inputs) { return g.create("y", inputs[0], axis); }; @@ -850,31 +866,30 @@ TEST(cpp_operations_test, softmax) { } } -TEST(cpp_operations_test, slice4d) { +TEST(cpp_operations_test, slice4d) +{ vector shape_data{5, 30, 40, 12}; - vector starts[] = {{0, 0, 0, 0}, - {1, 1, 1, 1}, - {1, 0, 1, 0}, - {0, 1, 1, 0}}; + vector starts[] = {{0, 0, 0, 0}, {1, 1, 1, 1}, {1, 0, 1, 0}, {0, 1, 1, 0}}; vector sizes[] = { - {-1, -1, -1, -1}, - {4, -1, 10, -1}, + {-1, -1, -1, -1}, {4, -1, 10, -1}, }; - for (auto st : starts) { - for (auto sz : sizes) { + for (auto st : starts) + { + for (auto sz : sizes) + { Tensor input_atensor; vector> input_n_tensor(1); fillTensors(input_n_tensor[0], input_atensor, shape_data, 1.0f); - auto op_gen = [st, sz](mir::Graph& g, const std::vector& inputs) { - return g.create("y", inputs[0], mir::Shape(st), - mir::Shape(sz)); + auto op_gen = [st, sz](mir::Graph &g, const std::vector &inputs) { + return g.create("y", inputs[0], mir::Shape(st), mir::Shape(sz)); }; createAndRunTestGraph(op_gen, slice, input_n_tensor, input_atensor); } } } -TEST(cpp_operations_test, reshape) { +TEST(cpp_operations_test, reshape) +{ // test prerequisites vector input_shape_data{2, 3, 4, 5}; vector output_shape_data{1, 120}; @@ -883,29 +898,31 @@ TEST(cpp_operations_test, reshape) { Tensor input_atensor; vector> input_ntensors(1); fillTensors(input_ntensors[0], input_atensor, input_shape_data, 1.0f); - auto op_generator = [&output_nshape](mir::Graph& g, - const std::vector& inputs) { + auto op_generator = [&output_nshape](mir::Graph &g, + const std::vector &inputs) { return g.create("y", inputs[0], output_nshape); }; createAndRunTestGraph(op_generator, reshape, input_ntensors, input_atensor); } -TEST(cpp_operations_test, sqrtTest) { +TEST(cpp_operations_test, sqrtTest) +{ // test prerequisites vector shape_data{2, 3, 4, 5}; Tensor input_atensor; vector> input_ntensor(1); fillTensors(input_ntensor[0], input_atensor, shape_data, 1.0f); - auto op_generator = [](mir::Graph& g, const std::vector& inputs) { + auto op_generator = [](mir::Graph &g, const std::vector &inputs) { return g.create("y", inputs[0]); }; createAndRunTestGraph(op_generator, sqrtFN, input_ntensor, input_atensor); } -TEST(cpp_operations_test, pad) { +TEST(cpp_operations_test, pad) +{ // test on matrix 2x3 - vector input_shape{2,3}; + vector input_shape{2, 3}; Tensor input_atensor; vector> input_ntensor(1); @@ -918,33 +935,31 @@ TEST(cpp_operations_test, pad) { float const_value = 0.0; - mir::Scalar constant_value(reinterpret_cast(&const_value), - mir::DataType::FLOAT32, sizeof(float)); + mir::Scalar constant_value(reinterpret_cast(&const_value), mir::DataType::FLOAT32, + sizeof(float)); - auto op_generator = [num_dims, &paddings, &constant_value] - (mir::Graph& g, const std::vector& inputs) { + auto op_generator = [num_dims, &paddings, &constant_value]( + mir::Graph &g, const std::vector &inputs) { return g.create("y", inputs[0], num_dims, paddings, constant_value); }; createAndRunTestGraph(op_generator, pad, input_ntensor, input_atensor); } -TEST(cpp_operations_test, transpose) { +TEST(cpp_operations_test, transpose) +{ // test transpose for 4 dims tensors vector input_shape_4d{2, 3, 4, 5}; Tensor input_atensor_4d; vector> input_ntensor_4d(1); fillTensors(input_ntensor_4d[0], input_atensor_4d, input_shape_4d, 1.0f); - vector test_cases_pack_4d[] = { - {0, 1, 2, 3}, - {1, 0, 2, 3}, - {3, 2, 1, 0} - }; - for (const auto& permute: test_cases_pack_4d) { - auto op_generator = [&permute](mir::Graph& g, - const std::vector& inputs) { - return g.create("transpose", inputs[0], permute); + vector test_cases_pack_4d[] = {{0, 1, 2, 3}, {1, 0, 2, 3}, {3, 2, 1, 0}}; + for (const auto &permute : test_cases_pack_4d) + { + auto op_generator = [&permute](mir::Graph &g, + const std::vector &inputs) { + return g.create("transpose", inputs[0], permute); }; createAndRunTestGraph(op_generator, transpose, input_ntensor_4d, input_atensor_4d); } @@ -954,18 +969,13 @@ TEST(cpp_operations_test, transpose) { Tensor input_atensor_3d; vector> input_ntensor_3d(1); fillTensors(input_ntensor_3d[0], input_atensor_3d, input_shape_3d, 1.0f); - vector test_cases_pack_3d[] = { - {0, 1, 2}, - {1, 0, 2}, - {2, 1, 0} - }; - for (const auto& permute: test_cases_pack_3d) { - auto op_generator = [&permute](mir::Graph& g, - const std::vector& inputs) { - return g.create("transpose", inputs[0], permute); + vector test_cases_pack_3d[] = {{0, 1, 2}, {1, 0, 2}, {2, 1, 0}}; + for (const auto &permute : test_cases_pack_3d) + { + auto op_generator = [&permute](mir::Graph &g, + const std::vector &inputs) { + return g.create("transpose", inputs[0], permute); }; createAndRunTestGraph(op_generator, transpose, input_ntensor_3d, input_atensor_3d); } - - } diff --git a/compiler/nnc/unittests/soft_backend/Generator.cpp b/compiler/nnc/unittests/soft_backend/Generator.cpp index 98f5179..50f55c6 100644 --- a/compiler/nnc/unittests/soft_backend/Generator.cpp +++ b/compiler/nnc/unittests/soft_backend/Generator.cpp @@ -33,56 +33,57 @@ using namespace std; using namespace nnc; using namespace mir; -static bool isFileExists(const string& path) { +static bool isFileExists(const string &path) +{ ifstream f(path); return f.good(); } -static void deleteFile(const string& path) { +static void deleteFile(const string &path) +{ int res = remove(path.c_str()); assert(!res && "failed to remove file"); (void)res; } -int removeRec(const char* fpath, const struct stat* /*sb*/, - int /*typeflag*/, struct FTW* /*ftwbuf*/) { +int removeRec(const char *fpath, const struct stat * /*sb*/, int /*typeflag*/, + struct FTW * /*ftwbuf*/) +{ deleteFile(fpath); return 0; } -static void deleteDir(const string& path) { +static void deleteDir(const string &path) +{ int res = nftw(path.c_str(), removeRec, 1, FTW_DEPTH | FTW_PHYS); assert(!res && "failed to remove dir"); (void)res; } -static void checkOutputExists(const string& common_path) { +static void checkOutputExists(const string &common_path) +{ ASSERT_TRUE(isFileExists(common_path + ".h")); ASSERT_TRUE(isFileExists(common_path + ".cpp")); ASSERT_TRUE(isFileExists(common_path + ".params")); } -static void emptyFile(const string& path) { - ofstream of(path); -} +static void emptyFile(const string &path) { ofstream of(path); } -TEST(Generator, check_generator_call) { - // assume here that c++ and c code generators behave identically in terms of parameters check - // test only c++ generator - #define TEST_DIR "output_dir" - #define TEST_NAME "someName" - #define BASE_NAME TEST_DIR "/" TEST_NAME - const char* argv[] = {"soft_backend_test", - "-d", TEST_DIR, - "-o", TEST_NAME, - nullptr}; +TEST(Generator, check_generator_call) +{ +// assume here that c++ and c code generators behave identically in terms of parameters check +// test only c++ generator +#define TEST_DIR "output_dir" +#define TEST_NAME "someName" +#define BASE_NAME TEST_DIR "/" TEST_NAME + const char *argv[] = {"soft_backend_test", "-d", TEST_DIR, "-o", TEST_NAME, nullptr}; int argc = (sizeof(argv) / sizeof(argv[0])) - 1; cli::CommandLine::getParser()->parseCommandLine(argc, argv, false); mir::Graph g; - Operation* input = g.create("input", Shape{1, 2, 3, 4}); - Operation* output = g.create("output", input->getOutput(0)); + Operation *input = g.create("input", Shape{1, 2, 3, 4}); + Operation *output = g.create("output", input->getOutput(0)); // test that generator creates output dir and files if (isFileExists(TEST_DIR)) diff --git a/compiler/nnc/unittests/soft_backend/ModelAnalyzer.cpp b/compiler/nnc/unittests/soft_backend/ModelAnalyzer.cpp index 0049097..1848dc1 100644 --- a/compiler/nnc/unittests/soft_backend/ModelAnalyzer.cpp +++ b/compiler/nnc/unittests/soft_backend/ModelAnalyzer.cpp @@ -27,14 +27,16 @@ using namespace nnc; using namespace mir; using namespace sir; -static const CallFunction* getCall(const unique_ptr& ptr) { - return dynamic_cast(ptr.get()); +static const CallFunction *getCall(const unique_ptr &ptr) +{ + return dynamic_cast(ptr.get()); } /* * This test designed to check basic layout properties of Model analyzer */ -TEST(ModelAnalyzer, linearization) { +TEST(ModelAnalyzer, linearization) +{ mir::Graph g; /* * Create graph: @@ -50,18 +52,18 @@ TEST(ModelAnalyzer, linearization) { * \ / * [join] */ - Operation* input = g.create("input", Shape{1, 2, 3}); - Operation* head1 = g.create("head1", input->getOutput(0)); - Operation* head2 = g.create("head2", input->getOutput(0)); - Operation* tail1 = g.create("tail1", head1->getOutput(0)); - Operation* tail2 = g.create("tail2", head2->getOutput(0)); - std::vector concat_inputs{tail1->getOutput(0), tail2->getOutput(0)}; - Operation* join = g.create("join", concat_inputs, 0); + Operation *input = g.create("input", Shape{1, 2, 3}); + Operation *head1 = g.create("head1", input->getOutput(0)); + Operation *head2 = g.create("head2", input->getOutput(0)); + Operation *tail1 = g.create("tail1", head1->getOutput(0)); + Operation *tail2 = g.create("tail2", head2->getOutput(0)); + std::vector concat_inputs{tail1->getOutput(0), tail2->getOutput(0)}; + Operation *join = g.create("join", concat_inputs, 0); // Check that layout is desired ModelAnalyzer ma; ma.analyze(&g); - const auto& seq = ma.getInferenceSequence(); + const auto &seq = ma.getInferenceSequence(); ASSERT_EQ(seq.size(), 6u); auto it = seq.begin(); ASSERT_EQ(getCall(*(it++))->mirOp, input); diff --git a/compiler/nnc/unittests/support/CommandLineTest.cpp b/compiler/nnc/unittests/support/CommandLineTest.cpp index e86b1c2..73f77aa 100644 --- a/compiler/nnc/unittests/support/CommandLineTest.cpp +++ b/compiler/nnc/unittests/support/CommandLineTest.cpp @@ -20,21 +20,11 @@ using namespace nnc::cli; +void soption_checker1(const Option &opt) { ASSERT_EQ(opt, "SOME_VALUE1,SOME_VALUE2"); } -void soption_checker1(const Option &opt) -{ - ASSERT_EQ(opt, "SOME_VALUE1,SOME_VALUE2"); -} - -void soption_checker2(const Option &opt) -{ - ASSERT_EQ(opt, "AAA_VALUE"); -} +void soption_checker2(const Option &opt) { ASSERT_EQ(opt, "AAA_VALUE"); } -void boption_checker(const Option &opt) -{ - ASSERT_EQ(opt, false); -} +void boption_checker(const Option &opt) { ASSERT_EQ(opt, false); } /** * declare command line options for testing @@ -50,84 +40,57 @@ Option SSingleOpt(optname("--single"), overview("description of option with single name")); // test option with several separators Option SSeveralSepOpt(optname("-several_separators"), - overview("description of option with several separators"), - "", - optional(false), - optvalues(""), - soption_checker1, + overview("description of option with several separators"), "", + optional(false), optvalues(""), soption_checker1, separators("=, :")); // test option with one separator Option SOneSepOpt(optname("--one_separarot"), - overview("description of option with one separator"), - "", - optional(false), - optvalues(""), - soption_checker2, - separators("=")); + overview("description of option with one separator"), "", + optional(false), optvalues(""), soption_checker2, separators("=")); // test option with defalut value Option SDefaultOpt(optname("-default_val_opt"), overview("description of option with default value"), "DEFAULT_VALUE"); // test optional option Option SOptionalOpt(optname("--optional_opt"), - overview("description of optional option"), - "", - optional(true)); + overview("description of optional option"), "", optional(true)); // test option with valid values Option SValidValsOpt(optname("-valid_opt"), - overview("description of option with valid values"), - "", - optional(true), - optvalues("value1, value2")); + overview("description of option with valid values"), "", + optional(true), optvalues("value1, value2")); // // declare integer options // // test option with negative value and valid values Option NNegOpt(optname("-neg_val"), - overview("description of integer option with negative value"), - -1, - optional(false), - optvalues("-42, -33")); + overview("description of integer option with negative value"), -1, + optional(false), optvalues("-42, -33")); // test option with default negative value -Option NDefaultNegOpt(optname("-default_neg_val"), - overview("description of integer option with default negative value"), - -33); +Option + NDefaultNegOpt(optname("-default_neg_val"), + overview("description of integer option with default negative value"), -33); // test option with positive values Option NPosOpt(optname("-pos_val"), - overview("description of integer option with positive value"), - 1, - optional(false), - optvalues("42, 33")); + overview("description of integer option with positive value"), 1, + optional(false), optvalues("42, 33")); // // declare char options // -Option CharOpt(optname("-char-opt"), - overview("description of char option"), - '\0', - optional(false), - optvalues("a, b")); - -Option DashOpt(optname("-dash_opt"), - overview("description of char option with dash value"), - '\0', - optional(false), - optvalues("-")); +Option CharOpt(optname("-char-opt"), overview("description of char option"), '\0', + optional(false), optvalues("a, b")); + +Option DashOpt(optname("-dash_opt"), overview("description of char option with dash value"), + '\0', optional(false), optvalues("-")); // // declare bool option // -Option BoolOpt(optname("-bool_opt"), - overview("description of bool option"), - true, - optional(false), - optvalues(""), - boption_checker, - separators("=")); -Option BoolOpt2(optname("-bool-opt2"), - overview("description of bool option with value")); +Option BoolOpt(optname("-bool_opt"), overview("description of bool option"), true, + optional(false), optvalues(""), boption_checker, separators("=")); +Option BoolOpt2(optname("-bool-opt2"), overview("description of bool option with value")); // // declare vector option @@ -138,8 +101,7 @@ Option> VecStrOpt2(optname("-vec_opt2"), overview("description of vector option")); Option> VecStrOptWithVals(optname("--vec_opt_with_vals"), overview("description of vector option"), - std::vector(), - optional(false), + std::vector(), optional(false), optvalues("abc, 123, xxx")); // // declare options in group @@ -147,79 +109,57 @@ Option> VecStrOptWithVals(optname("--vec_opt_with_vals" // // declare bool option // -Option GroupOpt1(optname("-group_opt1"), - overview("description of group option"), - true, - optional(false), - optvalues(""), - nullptr, - separators(""), - showopt(true), +Option GroupOpt1(optname("-group_opt1"), overview("description of group option"), true, + optional(false), optvalues(""), nullptr, separators(""), showopt(true), IOption::Group::caffe2); -Option GroupOpt2(optname("-group_opt2"), - overview("description of group option"), - std::string(), - optional(true), - optvalues(""), - nullptr, - separators(""), - showopt(true), - IOption::Group::caffe2); -Option GroupOpt3(optname("-group_opt3"), - overview("description of group option"), - 42, - optional(true), - optvalues(""), - nullptr, - separators(""), - showopt(true), +Option GroupOpt2(optname("-group_opt2"), overview("description of group option"), + std::string(), optional(true), optvalues(""), nullptr, separators(""), + showopt(true), IOption::Group::caffe2); +Option GroupOpt3(optname("-group_opt3"), overview("description of group option"), 42, + optional(true), optvalues(""), nullptr, separators(""), showopt(true), IOption::Group::onnx); // test options TEST(SUPPORT_NNC, verify_cl_options) { // create command line - const char *argv[] = {"CLTest", // program name - // string options - "-m", "multiopt_value", // second name for option with several names - "--single", "single_value", // option with single name - "-several_separators:SOME_VALUE1,SOME_VALUE2", // test option with several separators - "--one_separarot=AAA_VALUE", // test option whit one separator - "-default_val_opt", // test option with default value - "--optional_opt", "/home/guest/tmp", // test optional option - "-valid_opt", "value2", // test options with defined values - // integer options - "-neg_val", "-42", // test negative value for integer option - "-default_neg_val", // test integer option with default value - "-pos_val", "33", // test positive value for integer option - // char options - "-char-opt", "b", - "-dash_opt", "-", - // bool options - "-bool_opt=false", - "-bool-opt2", - // vector of strings options - "-vec_opt1", "1", "c", "222", "ABC", "857", - "-vec_opt2", - "--vec_opt_with_vals", "abc", "123", "xxx", "abc", "xxx", - // grouped options - "-group_opt1", - "-group_opt2", "abc", - "-group_opt3", "11", - nullptr}; + const char *argv[] = { + "CLTest", // program name + // string options + "-m", "multiopt_value", // second name for option with several names + "--single", "single_value", // option with single name + "-several_separators:SOME_VALUE1,SOME_VALUE2", // test option with several separators + "--one_separarot=AAA_VALUE", // test option whit one separator + "-default_val_opt", // test option with default value + "--optional_opt", "/home/guest/tmp", // test optional option + "-valid_opt", "value2", // test options with defined values + // integer options + "-neg_val", "-42", // test negative value for integer option + "-default_neg_val", // test integer option with default value + "-pos_val", "33", // test positive value for integer option + // char options + "-char-opt", "b", "-dash_opt", "-", + // bool options + "-bool_opt=false", "-bool-opt2", + // vector of strings options + "-vec_opt1", "1", "c", "222", "ABC", "857", "-vec_opt2", "--vec_opt_with_vals", "abc", "123", + "xxx", "abc", "xxx", + // grouped options + "-group_opt1", "-group_opt2", "abc", "-group_opt3", "11", nullptr}; int argc = (sizeof(argv) / sizeof(argv[0])) - 1; // It must be failed if option is not passed and other options are in the same group - argv[argc-5] = "-m"; // disable -group_opt1 + argv[argc - 5] = "-m"; // disable -group_opt1 ASSERT_DEATH(CommandLine::getParser()->parseCommandLine(argc, argv), ""); - argv[argc-5] = "-group_opt1"; // enable -group_opt1 + argv[argc - 5] = "-group_opt1"; // enable -group_opt1 - // test when mandatory grouped option is not passed. It must be OK if options being from the same group are missed - argv[argc-4] = "-m"; // disable -group_opt2 - argv[argc-2] = "-m"; // disable -group_opt3 + // test when mandatory grouped option is not passed. It must be OK if options being from the same + // group are missed + argv[argc - 4] = "-m"; // disable -group_opt2 + argv[argc - 2] = "-m"; // disable -group_opt3 CommandLine::getParser()->parseCommandLine(argc, argv); - argv[argc-4] = "-group_opt2"; // enable -group_opt2 - argv[argc-2] = "-group_opt3"; // enable -group_opt3 + argv[argc - 4] = "-group_opt2"; // enable -group_opt2 + argv[argc - 2] = "-group_opt3"; // enable -group_opt3 // parse command line CommandLine::getParser()->parseCommandLine(argc, argv); diff --git a/compiler/nnc/unittests/tflite_frontend/test_data/gen_test.py b/compiler/nnc/unittests/tflite_frontend/test_data/gen_test.py index bafbf80..74a566d 100755 --- a/compiler/nnc/unittests/tflite_frontend/test_data/gen_test.py +++ b/compiler/nnc/unittests/tflite_frontend/test_data/gen_test.py @@ -4,22 +4,25 @@ from distutils.version import LooseVersion, StrictVersion try: import numpy as np except ImportError: - print("!! NumPy is not installed, tflite frontend test not generated", file=sys.stderr) + print( + "!! NumPy is not installed, tflite frontend test not generated", file=sys.stderr) exit(1) try: import tensorflow as tf if (LooseVersion(tf.VERSION) < LooseVersion("1.11.0")): raise (Exception("Wrong Version")) except: - print("!! Tensorflow v 1.11 not installed, tflite frontend test not generated", file=sys.stderr) + print( + "!! Tensorflow v 1.11 not installed, tflite frontend test not generated", + file=sys.stderr) exit(1) resDir = sys.argv[1] -if resDir[-1]!="/": resDir +="/" +if resDir[-1] != "/": resDir += "/" output_shape = [1, 28, 28, 1] -strides = [1,1,1,1] -W = tf.constant(np.ones([7, 7, 1, 1]).astype(np.float32), name = "ker_d") +strides = [1, 1, 1, 1] +W = tf.constant(np.ones([7, 7, 1, 1]).astype(np.float32), name="ker_d") # Create the graph. X = tf.placeholder(shape=[1, 28, 28, 1], name='input', dtype=tf.float32) @@ -28,10 +31,11 @@ Y = tf.sin(X) out0 = tf.identity(Y, name="out") # Filter the input image. with tf.Session() as sess: - out = sess.run(out0, feed_dict = {"input:0": np.ones((1, 28, 28, 1)).astype(np.float32)}) + out = sess.run( + out0, feed_dict={"input:0": np.ones((1, 28, 28, 1)).astype(np.float32)}) frozen_graphdef = tf.graph_util.convert_variables_to_constants( sess, sess.graph_def, ["out"]) converter = tf.contrib.lite.TocoConverter.from_session(sess, [X], [out0]) tflite_model = converter.convert() - open(resDir+"unsupported.tflite", "wb").write(tflite_model) + open(resDir + "unsupported.tflite", "wb").write(tflite_model) diff --git a/compiler/nnc/unittests/tflite_frontend/unsupported_tflite_model.cpp b/compiler/nnc/unittests/tflite_frontend/unsupported_tflite_model.cpp index 450f1fb..8436fdb 100644 --- a/compiler/nnc/unittests/tflite_frontend/unsupported_tflite_model.cpp +++ b/compiler/nnc/unittests/tflite_frontend/unsupported_tflite_model.cpp @@ -8,15 +8,18 @@ const char *ErrorMsg = "NNC can't load model. Detected problems:\n" " * SIN: unsupported operator"; // When adding support for new layers, change the model, not the test -TEST(TFLITE_IMPORT_UNSUPPORTED, ImportModelWithUnsupportedLayers) { +TEST(TFLITE_IMPORT_UNSUPPORTED, ImportModelWithUnsupportedLayers) +{ std::string filename = std::string(TFLITE_TEST_DIR) + "unsupported.tflite"; std::cout << filename << "\n"; nnc::TfliteImporterPass importer{filename}; - try { + try + { importer.importModel(); } - catch (nnc::PassException &e) { + catch (nnc::PassException &e) + { ASSERT_EQ(std::string(ErrorMsg), e.what()); importer.cleanup(); return; diff --git a/compiler/nnc/utils/caffe2_dot_dumper/model_dump.cpp b/compiler/nnc/utils/caffe2_dot_dumper/model_dump.cpp index 2ae8a55..00d53c2 100644 --- a/compiler/nnc/utils/caffe2_dot_dumper/model_dump.cpp +++ b/compiler/nnc/utils/caffe2_dot_dumper/model_dump.cpp @@ -27,19 +27,22 @@ using namespace nnc; using namespace mir; using namespace nnc::cli; -int main(int argc, const char **argv) { +int main(int argc, const char **argv) +{ cli::CommandLine::getParser()->parseCommandLine(argc, argv, false); // FIXME: caffe2 input shapes are not provided by model and must be set from cli nnc::Caffe2ImporterPass importer{cli::inputFile, cli::initNet, {cli::inputShapes}}; - try { + try + { IrDotDumper dotDumper; auto g = static_cast(importer.importModel()); g->accept(&dotDumper); dotDumper.writeDot(std::cout); } - catch (PassException &e) { + catch (PassException &e) + { std::cout << "Error: " << e.what() << std::endl; return -1; } diff --git a/compiler/nnc/utils/caffe_dot_dumper/model_dump.cpp b/compiler/nnc/utils/caffe_dot_dumper/model_dump.cpp index 83d7d36..e4b594d 100644 --- a/compiler/nnc/utils/caffe_dot_dumper/model_dump.cpp +++ b/compiler/nnc/utils/caffe_dot_dumper/model_dump.cpp @@ -27,17 +27,20 @@ using namespace nnc; using namespace mir; using namespace nnc::cli; -int main(int argc, const char **argv) { +int main(int argc, const char **argv) +{ cli::CommandLine::getParser()->parseCommandLine(argc, argv, false); nnc::CaffeImporterPass importer{cli::inputFile}; - try { + try + { IrDotDumper dotDumper; auto g = importer.importModel(); g->accept(&dotDumper); dotDumper.writeDot(std::cout); } - catch (PassException &e) { + catch (PassException &e) + { std::cout << "Error: " << e.what() << std::endl; return -1; } diff --git a/compiler/nnc/utils/caffe_model_maker/GenerateCaffeModels.py b/compiler/nnc/utils/caffe_model_maker/GenerateCaffeModels.py index b1ed9d4..ca8b377 100644 --- a/compiler/nnc/utils/caffe_model_maker/GenerateCaffeModels.py +++ b/compiler/nnc/utils/caffe_model_maker/GenerateCaffeModels.py @@ -185,8 +185,7 @@ OPS = [ ( 'HDF5Data', { - 'source': - 'in', # This is the name of the file WITH HDF5 FILENAMES 0_0 + 'source': 'in', # This is the name of the file WITH HDF5 FILENAMES 0_0 # Top should have the same name as the dataset in the hdf5 file # FIXME Requires Caffegen to be built with Caffe that supports LMDB 'batch_size': 1, @@ -399,8 +398,7 @@ OPS = [ ( 'ArgMax', { - 'out_max_val': - False, # ok # if True, outputs pairs (argmax, maxval) # ok + 'out_max_val': False, # ok # if True, outputs pairs (argmax, maxval) # ok 'top_k': 1, 'axis': -1 }), @@ -458,7 +456,7 @@ OPS = [ 'base': -1.0, # ok 'scale': 1.0, 'shift': PH(float, (2.0, 10.0)), - 'how_many' : 10 + 'how_many': 10 }), # y = ln(shift + scale * x) (log_base() for base > 0) ( 'Power', @@ -644,8 +642,8 @@ class Layer: if self.args == None: self.args = dict() self.num_inp = self.args.pop("inputs", 1) self.num_out = self.args.pop("outputs", 1) - self.special_shape = self.args.pop( - "special_shape", False) # 2nd input has special shape + self.special_shape = self.args.pop("special_shape", + False) # 2nd input has special shape self.is_data = self.args.pop("is_data", False) self.is_notop = self.args.pop("is_notop", False) @@ -665,29 +663,27 @@ class Layer: net.data1 = L.DummyData(data_filler=cofil, shape={'dim': [1, 4]}) net.data2 = L.DummyData(data_filler=cofil, shape={'dim': [1, 1]}) - net.op = getattr(L, self.name)(net.data, net.data1, net.data2, - **self.args) + net.op = getattr(L, self.name)(net.data, net.data1, net.data2, **self.args) # this covers most cases else: net.data = L.Input(shape={'dim': [1, 3, LS, LS]}) if self.num_inp == 2: - net.data1 = L.DummyData( - data_filler=cofil, shape={'dim': [1, 3, LS, LS]}) + net.data1 = L.DummyData(data_filler=cofil, shape={'dim': [1, 3, LS, LS]}) elif self.num_inp > 2: for i in range(1, self.num_inp): setattr( net, "data" + str(i), - L.DummyData( - data_filler=cofil, shape={'dim': EXTRA_SHAPES[i]})) + L.DummyData(data_filler=cofil, shape={'dim': EXTRA_SHAPES[i]})) if self.special_shape: net.data = L.Input(shape={'dim': [1, 3, 1, 1]}) net.data1 = L.DummyData( data_filler=cofil, shape={'dim': self.special_shape}) - net.op = getattr(L, self.name)(net.data, *[ - getattr(net, "data" + str(i)) for i in range(1, self.num_inp) - ], **self.args) + net.op = getattr(L, self.name)( + net.data, + *[getattr(net, "data" + str(i)) + for i in range(1, self.num_inp)], **self.args) if self.is_notop: net.op.fn.tops = OrderedDict() @@ -706,10 +702,7 @@ class LayerMaker: self.how_many = self.args.pop("how_many", 1) def make(self): - return [ - Layer(self.name, traverse(self.args, mock)) - for i in range(self.how_many) - ] + return [Layer(self.name, traverse(self.args, mock)) for i in range(self.how_many)] layer_gen = chain(*map(lambda para: LayerMaker(para).make(), OPS)) @@ -721,8 +714,7 @@ for layer in layer_gen: n = layer.make_net() counter[layer.name] += 1 - with open(filename.format(layer.name, counter[layer.name] - 1), - 'w+') as ptxt_file: + with open(filename.format(layer.name, counter[layer.name] - 1), 'w+') as ptxt_file: print(n.to_proto(), file=ptxt_file) if layer.name == "Python": # Special case for python layer diff --git a/compiler/nnc/utils/caffe_model_maker/Pyloss.py b/compiler/nnc/utils/caffe_model_maker/Pyloss.py index 3abff7f..ee32b9e 100644 --- a/compiler/nnc/utils/caffe_model_maker/Pyloss.py +++ b/compiler/nnc/utils/caffe_model_maker/Pyloss.py @@ -16,6 +16,7 @@ limitations under the License. import caffe import numpy as np + class EuclideanLossLayer(caffe.Layer): """ Compute the Euclidean Loss in the same manner as the C++ EuclideanLossLayer diff --git a/compiler/nnc/utils/def2src.cpp b/compiler/nnc/utils/def2src.cpp index 208e26f..32a3e48 100644 --- a/compiler/nnc/utils/def2src.cpp +++ b/compiler/nnc/utils/def2src.cpp @@ -18,15 +18,18 @@ #include #include -int fileToArray(const std::string& source, const std::string& dest, const std::string& arrName) { - FILE* fs = fopen(source.c_str(), "rb"); - if (!fs) { +int fileToArray(const std::string &source, const std::string &dest, const std::string &arrName) +{ + FILE *fs = fopen(source.c_str(), "rb"); + if (!fs) + { std::cerr << "source file not found: <" << source << ">" << std::endl; return -1; } std::ofstream fo(dest.c_str()); - if (fo.fail()) { + if (fo.fail()) + { std::cerr << "cannot generate file: <" << dest << ">" << std::endl; fclose(fs); return -1; @@ -43,13 +46,15 @@ int fileToArray(const std::string& source, const std::string& dest, const std::s assert(!is_error); (void)is_error; size_t bytes; - do { + do + { char buf[1024]; bytes = fread(buf, 1, sizeof(buf), fs); assert(!ferror(fs) && "file read error"); - + // convert line - for (size_t i = 0; i < bytes; i++) { + for (size_t i = 0; i < bytes; i++) + { fo << "0x" << std::hex << static_cast(buf[i]) << ", "; } } while (bytes != 0); @@ -78,13 +83,15 @@ std::string extractFileName(std::string path) return path; } -int main(int argc, char *argv[]) { +int main(int argc, char *argv[]) +{ if (argc < 3) return -1; std::string OutPutDir = argv[1]; - for (int i = 2; i < argc; i++) { + for (int i = 2; i < argc; i++) + { std::string sourceFullFileName = argv[i]; std::string filename = extractFileName(sourceFullFileName); // NOLINTNEXTLINE (performance-inefficient-string-concatenation) diff --git a/compiler/nnc/utils/infer_tests/infer_testcases.py b/compiler/nnc/utils/infer_tests/infer_testcases.py index be77fd2..fab887c 100644 --- a/compiler/nnc/utils/infer_tests/infer_testcases.py +++ b/compiler/nnc/utils/infer_tests/infer_testcases.py @@ -11,8 +11,8 @@ import datetime # -b - specifies path to nnkit build folder, inside which tools/run is located # -f - specifies framework ('tfl' for tflite or 'caf' for caffe) that the model belogs to # -t - specifies path to testcase folder (see it's structure in readme) -# -p - allow some sort of parallelism by processing only a subset of files, -# you need to specify number of processes and run as much of them +# -p - allow some sort of parallelism by processing only a subset of files, +# you need to specify number of processes and run as much of them # manually with diferent numbers # -r - infer all testcases regardless of whether the result files are present # last argument(s) is the model to infer @@ -26,7 +26,8 @@ helpstr = "Expected arguments: -b " + \ "-t " + \ "[-p ] " + \ "[-r] " + \ - "( | )" + "( | )" + def eprint(*args, **kwargs): print(*args, file=sys.stderr, **kwargs) @@ -37,13 +38,13 @@ proc_num = 1 min_argc = 8 args = {} -args['-p'] = (1, 1) +args['-p'] = (1, 1) args['-r'] = False argc = len(sys.argv) for i in range(argc): arg = sys.argv[i] - if arg =='-r': + if arg == '-r': args[arg] = True elif arg == '-b' or arg == '-f' or arg == '-t': if i + 1 >= argc: @@ -92,33 +93,37 @@ print('Testcases folder: ', testcases_dir) hdf_suffix = '.hdf5' bin_suffix = '.dat' + def get_command_caf(infilename, outfilename, proto, caffemodel): - return [build_path + "/tools/run/nnkit-run", - "--pre", build_path + "/actions/HDF5/libnnkit_HDF5_import_action.so", - "--pre-arg", infilename, - "--backend", build_path + "/backends/caffe/libnnkit_caffe_backend.so", - "--backend-arg", proto, - "--backend-arg", caffemodel, - "--post", build_path + "/actions/HDF5/libnnkit_HDF5_export_action.so", - "--post-arg", outfilename] + return [ + build_path + "/tools/run/nnkit-run", "--pre", + build_path + "/actions/HDF5/libnnkit_HDF5_import_action.so", "--pre-arg", + infilename, "--backend", build_path + "/backends/caffe/libnnkit_caffe_backend.so", + "--backend-arg", proto, "--backend-arg", caffemodel, "--post", + build_path + "/actions/HDF5/libnnkit_HDF5_export_action.so", "--post-arg", + outfilename + ] + def get_command_tfl(infilename, outfilename, model_file): - return [build_path + "/tools/run/nnkit-run", - "--pre", build_path + "/actions/HDF5/libnnkit_HDF5_import_action.so", - "--pre-arg", infilename, - "--backend", build_path + "/backends/tflite/libnnkit_tflite_backend.so", - "--backend-arg", model_file, - "--post", build_path + "/actions/builtin/libnnkit_show_action.so", - "--post", build_path + "/actions/HDF5/libnnkit_HDF5_export_action.so", - "--post-arg", outfilename] + return [ + build_path + "/tools/run/nnkit-run", "--pre", + build_path + "/actions/HDF5/libnnkit_HDF5_import_action.so", "--pre-arg", + infilename, "--backend", + build_path + "/backends/tflite/libnnkit_tflite_backend.so", "--backend-arg", + model_file, "--post", build_path + "/actions/builtin/libnnkit_show_action.so", + "--post", build_path + "/actions/HDF5/libnnkit_HDF5_export_action.so", + "--post-arg", outfilename + ] + testcase_num = 0 testcases = glob.glob(testcases_dir + '/testcase*') -#testcases = [t -# for t in testcases +#testcases = [t +# for t in testcases # if remove_existing -# or len(glob.glob(t + '/output/output' + hdf_suffix)) == 0 +# or len(glob.glob(t + '/output/output' + hdf_suffix)) == 0 # or len(glob.glob(t + '/output/output' + bin_suffix)) == 0] testcases = testcases[proc_num - 1::nproc] @@ -144,7 +149,6 @@ for testcase in testcases: else: eprint(testcase, ': input not found') except: - eprint(testcase, 'failed') - -eprint('ended at', datetime.datetime.now()) + eprint(testcase, 'failed') +eprint('ended at', datetime.datetime.now()) diff --git a/compiler/nnc/utils/infer_tests/res2bin.py b/compiler/nnc/utils/infer_tests/res2bin.py index dcbfbd1..0c21848 100644 --- a/compiler/nnc/utils/infer_tests/res2bin.py +++ b/compiler/nnc/utils/infer_tests/res2bin.py @@ -3,30 +3,31 @@ import h5py import struct import sys -# This script takes hdf5 file and unfolds it in a vector of float values +# This script takes hdf5 file and unfolds it in a vector of float values # which is then writen in binary format to a given file # This is used by infer_testcases.py + def res2bin(infilename, outfilename): -# print("Input filename: ", infilename) -# print("Output filename: " , outfilename) - - f = h5py.File(infilename) - dset = f[list(f.keys())[0]] - - vals = np.zeros(np.shape(dset), dtype='float32') - for i in range(np.size(dset,0)): - vals[i,:] = np.asarray(dset[i], dtype='float32') - vals = list(np.reshape(vals, (vals.size))) - - with open(outfilename, 'wb') as outfile: - outfile.write(struct.pack('f'*len(vals), *vals)) + # print("Input filename: ", infilename) + # print("Output filename: " , outfilename) -if __name__ == '__main__': - argc = len(sys.argv) - if (argc > 2): - res2bin(sys.argv[1], sys.argv[2]) - else: - print("Not enough arguments, expected: hdf5 filename, output filename") - exit() + f = h5py.File(infilename) + dset = f[list(f.keys())[0]] + + vals = np.zeros(np.shape(dset), dtype='float32') + for i in range(np.size(dset, 0)): + vals[i, :] = np.asarray(dset[i], dtype='float32') + vals = list(np.reshape(vals, (vals.size))) + with open(outfilename, 'wb') as outfile: + outfile.write(struct.pack('f' * len(vals), *vals)) + + +if __name__ == '__main__': + argc = len(sys.argv) + if (argc > 2): + res2bin(sys.argv[1], sys.argv[2]) + else: + print("Not enough arguments, expected: hdf5 filename, output filename") + exit() diff --git a/compiler/nnc/utils/input_gen/tensor_gen.cpp b/compiler/nnc/utils/input_gen/tensor_gen.cpp index 0c7a36c..a9a2f5d 100644 --- a/compiler/nnc/utils/input_gen/tensor_gen.cpp +++ b/compiler/nnc/utils/input_gen/tensor_gen.cpp @@ -26,14 +26,17 @@ using namespace std; class Tensor; -static void iterate(Tensor& tensor, function&)> on_loop); +static void iterate(Tensor &tensor, function &)> on_loop); -class Tensor { +class Tensor +{ public: - explicit Tensor(const vector& shape) : _shape(shape), _data(0), _num_elems(1) { + explicit Tensor(const vector &shape) : _shape(shape), _data(0), _num_elems(1) + { _strides.resize(shape.size()); - for (int i = _shape.size() - 1; i >= 0; --i) { + for (int i = _shape.size() - 1; i >= 0; --i) + { _strides[i] = _num_elems; _num_elems *= _shape[i]; } @@ -44,10 +47,11 @@ public: ~Tensor() { delete[] _data; } int rank() const { return _shape.size(); } int dim(int d) const { return _shape[d]; } - float* data() { return _data; } + float *data() { return _data; } float numElems() const { return _num_elems; } - float& at(const vector& coords) { + float &at(const vector &coords) + { int offset = 0; for (auto i = 0; i < coords.size(); ++i) @@ -56,14 +60,15 @@ public: return _data[offset]; } - Tensor transpose(const vector& reshape) { + Tensor transpose(const vector &reshape) + { vector tr_shape(_shape.size()); for (auto i = 0; i < _shape.size(); ++i) tr_shape[i] = _shape[reshape[i]]; Tensor result(tr_shape); - auto on_loop = [this, &reshape, &result](vector& coords) { + auto on_loop = [this, &reshape, &result](vector &coords) { vector tr_coords(_shape.size()); for (int i = 0; i < rank(); ++i) @@ -78,20 +83,23 @@ public: private: vector _shape; vector _strides; - float* _data; + float *_data; hsize_t _num_elems; }; -static void fillTensor(Tensor& tensor) { +static void fillTensor(Tensor &tensor) +{ int v = 10; - for (int i = 0; i < tensor.numElems(); ++i) { + for (int i = 0; i < tensor.numElems(); ++i) + { tensor.data()[i] = v; v += 10; } } -static void iterate(Tensor& tensor, function&)> on_loop) { +static void iterate(Tensor &tensor, function &)> on_loop) +{ int num_dims = tensor.rank(); vector coords(num_dims, 0); vector dims(num_dims); @@ -99,12 +107,15 @@ static void iterate(Tensor& tensor, function&)> on_loop) { for (int i = 0; i < num_dims; ++i) dims[i] = tensor.dim(i); - for (;;) { + for (;;) + { on_loop(coords); int i; - for (i = num_dims - 1; i >= 0; --i) { - if (coords[i] < dims[i] - 1) { + for (i = num_dims - 1; i >= 0; --i) + { + if (coords[i] < dims[i] - 1) + { ++coords[i]; break; } @@ -112,14 +123,16 @@ static void iterate(Tensor& tensor, function&)> on_loop) { if (i < 0) break; - + fill(coords.begin() + i + 1, coords.end(), 0); } } -static void dumpTensor(Tensor& tensor) { - auto on_loop = [&tensor](vector& coords) { - for (int i = 0; i < tensor.rank(); ++i) { +static void dumpTensor(Tensor &tensor) +{ + auto on_loop = [&tensor](vector &coords) { + for (int i = 0; i < tensor.rank(); ++i) + { if (i > 0) cout << ", "; @@ -134,43 +147,57 @@ static void dumpTensor(Tensor& tensor) { static vector dimensions; -static void writeTensorToDatFile(const string& file_name, Tensor& tensor) { +static void writeTensorToDatFile(const string &file_name, Tensor &tensor) +{ ofstream of(file_name + ".dat", ios_base::binary); if (of.fail()) cout << "Could not output tensor to the: " << file_name + ".dat"; - of.write(reinterpret_cast(tensor.data()), tensor.numElems() * sizeof(float)); + of.write(reinterpret_cast(tensor.data()), tensor.numElems() * sizeof(float)); } -static void writeTensorToHDF5File(const string& tensor_name, const string& file_name, Tensor& tensor) { +static void writeTensorToHDF5File(const string &tensor_name, const string &file_name, + Tensor &tensor) +{ H5::H5File h5File(file_name + ".hdf5", H5F_ACC_TRUNC); H5::DataSpace dataspace(dimensions.size(), &dimensions[0]); auto dataset = h5File.createDataSet(tensor_name, H5::PredType::IEEE_F32BE, dataspace); dataset.write(tensor.data(), H5::PredType::NATIVE_FLOAT); } -int main(int argc, char* argv[]) { - if (argc < 4) { - cout << "Usage: " << argv[0] << " dim0, dim1, dim2, ..." << endl; +int main(int argc, char *argv[]) +{ + if (argc < 4) + { + cout << "Usage: " << argv[0] << " dim0, dim1, dim2, ..." + << endl; cout << "Where: dim0, dim1, dim2, ... are the generated tensor shape dimensions" << endl; return 1; } - for (int i = 3; i < argc; ++i) { - try { + for (int i = 3; i < argc; ++i) + { + try + { int d = stoi(argv[i]); - if (d <= 0) { - cout << "The dimensions must be positive values. This is not a correct dimension value: " << d << endl; + if (d <= 0) + { + cout << "The dimensions must be positive values. This is not a correct dimension value: " + << d << endl; return 1; } dimensions.push_back(d); - } catch(const invalid_argument&) { + } + catch (const invalid_argument &) + { cout << "The parameter does not look as an integer value: " << argv[i] << endl; return 1; - } catch(const out_of_range&) { + } + catch (const out_of_range &) + { cout << "The value is out of the C++ \"int\" type range: " << argv[i] << endl; return 1; } diff --git a/compiler/nnc/utils/model_runner/common_place.py b/compiler/nnc/utils/model_runner/common_place.py index 65c3d03..eb89534 100644 --- a/compiler/nnc/utils/model_runner/common_place.py +++ b/compiler/nnc/utils/model_runner/common_place.py @@ -14,15 +14,21 @@ def regular_step(): parser.add_argument( '-m', '--model', - help=("specify input file with NN model, \n[depends from model, " + help=("specify input file with NN model, \n[depends from model, " " two for caffe and caffe2, one for onnx and tflite]"), nargs='+') - parser.add_argument('-i', '--input', help=(" specify file with neural" - " network input data, hdf5 for caffe caffe2 tflite " - "and pb for onnx"), required=True) - parser.add_argument('-o', '--output_path', - help='here you specify which place will hold your output, default here', default='') - + parser.add_argument( + '-i', + '--input', + help=(" specify file with neural" + " network input data, hdf5 for caffe caffe2 tflite " + "and pb for onnx"), + required=True) + parser.add_argument( + '-o', + '--output_path', + help='here you specify which place will hold your output, default here', + default='') args = parser.parse_args() # added to check is our input file or not. most simple way @@ -40,7 +46,6 @@ def regular_step(): except IOError as e: print('model you enter doesnt exist, write correct PATH ') - return args diff --git a/compiler/nnc/utils/model_runner/model_runner_caffe.py b/compiler/nnc/utils/model_runner/model_runner_caffe.py index 2bb4092..a2e9427 100644 --- a/compiler/nnc/utils/model_runner/model_runner_caffe.py +++ b/compiler/nnc/utils/model_runner/model_runner_caffe.py @@ -15,7 +15,8 @@ def run_caffe(model_topology, model_weight, input_path, output_path=''): save_result(output_path, out) print(out) + if __name__ == '__main__': args = regular_step() - run_caffe(args.model[0], args.model[1], args.input, args.output_path) \ No newline at end of file + run_caffe(args.model[0], args.model[1], args.input, args.output_path) diff --git a/compiler/nnc/utils/model_runner/model_runner_caffe2.py b/compiler/nnc/utils/model_runner/model_runner_caffe2.py index 877af28..0c8feca 100644 --- a/compiler/nnc/utils/model_runner/model_runner_caffe2.py +++ b/compiler/nnc/utils/model_runner/model_runner_caffe2.py @@ -3,7 +3,7 @@ from common_place import * from caffe2.python import workspace -def run_caffe2(init_net, predict_net, input_path, output_path =''): +def run_caffe2(init_net, predict_net, input_path, output_path=''): x = read_input(input_path) with open(init_net, 'rb') as f: init_net = f.read() @@ -16,7 +16,8 @@ def run_caffe2(init_net, predict_net, input_path, output_path =''): print(results) save_result(output_path, results) + if __name__ == '__main__': args = regular_step() - run_caffe2(args.model[0], args.model[1], args.input, args.output_path) \ No newline at end of file + run_caffe2(args.model[0], args.model[1], args.input, args.output_path) diff --git a/compiler/nnc/utils/model_runner/model_runner_onnx.py b/compiler/nnc/utils/model_runner/model_runner_onnx.py index 9506b8e..6e0e8a6 100644 --- a/compiler/nnc/utils/model_runner/model_runner_onnx.py +++ b/compiler/nnc/utils/model_runner/model_runner_onnx.py @@ -3,7 +3,8 @@ from common_place import * import onnx import caffe2.python.onnx.backend -def run_onnx(model, input_path, output_path=''): #args.model[0] , args.input + +def run_onnx(model, input_path, output_path=''): #args.model[0] , args.input path = model #I'll leave it in case anyone needs to read the .pb file. @@ -19,6 +20,7 @@ def run_onnx(model, input_path, output_path=''): #args.model[0] , args.input print(output) save_result(output_path, output) + if __name__ == '__main__': args = regular_step() diff --git a/compiler/nnc/utils/model_runner/model_runner_tflite.py b/compiler/nnc/utils/model_runner/model_runner_tflite.py index 2b32aaf..80847b7 100644 --- a/compiler/nnc/utils/model_runner/model_runner_tflite.py +++ b/compiler/nnc/utils/model_runner/model_runner_tflite.py @@ -1,6 +1,7 @@ from common_place import * import tensorflow as tf + def run_tflite(model, input_path, output_path=''): input = read_input(input_path) @@ -17,6 +18,7 @@ def run_tflite(model, input_path, output_path=''): print(output_data) save_result(output_path, output_data) + if __name__ == '__main__': args = regular_step() diff --git a/compiler/nnc/utils/prepare_inputs/jpeg2hdf5.py b/compiler/nnc/utils/prepare_inputs/jpeg2hdf5.py index c5e9693..54f12b0 100644 --- a/compiler/nnc/utils/prepare_inputs/jpeg2hdf5.py +++ b/compiler/nnc/utils/prepare_inputs/jpeg2hdf5.py @@ -13,8 +13,8 @@ import datetime # -i - specifies input node name of the model that will use them (required by nnkit) # -r - if files already exist, rewrites them # -b - enable binary file generation -# -p - allow some sort of parallelism by processing only a subset of files, -# you need to specify number of processes and run as much of them +# -p - allow some sort of parallelism by processing only a subset of files, +# you need to specify number of processes and run as much of them # manually with diferent numbers # # Example: @@ -70,7 +70,7 @@ indirname = args['-t'] if not '-i' in args: if fw == 'caf': inputname = 'data' - elif fw =='tfl': + elif fw == 'tfl': inputname = 'input' else: inputname = args['-i'] @@ -86,81 +86,85 @@ testcases = testcases[proc_num - 1::nproc] number = 0 for testcase in testcases: - try: - infilename = glob.glob(testcase + 'input/*.JPEG') - if len(infilename) > 0: - number += 1 - infilename = infilename[0] - outfilename = testcase + 'input/' + infilename.split('/')[-1] + '.hdf5' - binoutfilename = testcase + 'input/' + infilename.split('/')[-1] + '.dat' - found_hdf = len(glob.glob(outfilename)) != 0 - found_bin = len(glob.glob(binoutfilename)) != 0 - if not found_hdf or (not found_bin and gen_binary) or remove_existing: - with Image.open(infilename) as im: - #TODO: check if order is correct here and in other places - h = im.size[0] - w = im.size[1] - s = im.split() - if len(s) == 3: - r, g, b = s - else: - r = s[0] - g = s[0] - b = s[0] - rf = r.convert('F') - gf = g.convert('F') - bf = b.convert('F') - rfb = rf.tobytes() - gfb = gf.tobytes() - bfb = bf.tobytes() - - made_hdf = False - if not found_hdf or remove_existing: - if fw == 'tfl': - reds = np.fromstring(rfb, count=(h * w), dtype='float32') - greens = np.fromstring(gfb, count=(h * w), dtype='float32') - blues = np.fromstring(bfb, count=(h * w), dtype='float32') - - dset_shape = (1, h, w, 3) - narr = np.ndarray(shape=(0)) - mixed_ch = [] - for i in range(h * w): - mixed_ch += [reds[i] / 255.0, greens[i] / 255.0, blues[i] / 255.0] - narr = np.append(narr, mixed_ch) - elif fw == 'caf': - dset_shape = (1, 3, h, w) - narr = np.fromstring(rfb + gfb + bfb, count=(3 * h * w), dtype='float32') - for i in range(3 * h * w): - narr[i] /= 255.0 - if remove_existing: - subprocess.call(['rm', '-f', outfilename]) - with h5py.File(outfilename) as f: - # nnkit hdf5_import asserts to use IEEE_F32BE, which is >f4 in numpy - dset = f.require_dataset(inputname, dset_shape, dtype='>f4') - dset[0] = np.reshape(narr, dset_shape) - made_hdf = True - - if gen_binary and (not found_bin or remove_existing): - if fw == 'tfl' and made_hdf: - l = narr.tolist() - else: - reds = np.fromstring(rfb, count=(h * w), dtype='float32') - greens = np.fromstring(gfb, count=(h * w), dtype='float32') - blues = np.fromstring(bfb, count=(h * w), dtype='float32') - l = np.ndarray(shape=(0)) - mixed_ch = [] - for i in range(h * w): - mixed_ch += [reds[i] / 255.0, greens[i] / 255.0, blues[i] / 255.0] - l = np.append(l, mixed_ch) - l = l.tolist() - with open(binoutfilename, 'wb') as out: - out.write(struct.pack('f'*len(l), *l)) - print(number, ': ' + testcase + ' Done') - else: - print(testcase, ' nothing to do') - else: - print(testcase, ' JPEG not found') - except: - print(testcase, " FAILED") -print('started at', ended.datetime.now()) + try: + infilename = glob.glob(testcase + 'input/*.JPEG') + if len(infilename) > 0: + number += 1 + infilename = infilename[0] + outfilename = testcase + 'input/' + infilename.split('/')[-1] + '.hdf5' + binoutfilename = testcase + 'input/' + infilename.split('/')[-1] + '.dat' + found_hdf = len(glob.glob(outfilename)) != 0 + found_bin = len(glob.glob(binoutfilename)) != 0 + if not found_hdf or (not found_bin and gen_binary) or remove_existing: + with Image.open(infilename) as im: + #TODO: check if order is correct here and in other places + h = im.size[0] + w = im.size[1] + s = im.split() + if len(s) == 3: + r, g, b = s + else: + r = s[0] + g = s[0] + b = s[0] + rf = r.convert('F') + gf = g.convert('F') + bf = b.convert('F') + rfb = rf.tobytes() + gfb = gf.tobytes() + bfb = bf.tobytes() + + made_hdf = False + if not found_hdf or remove_existing: + if fw == 'tfl': + reds = np.fromstring(rfb, count=(h * w), dtype='float32') + greens = np.fromstring(gfb, count=(h * w), dtype='float32') + blues = np.fromstring(bfb, count=(h * w), dtype='float32') + dset_shape = (1, h, w, 3) + narr = np.ndarray(shape=(0)) + mixed_ch = [] + for i in range(h * w): + mixed_ch += [ + reds[i] / 255.0, greens[i] / 255.0, blues[i] / 255.0 + ] + narr = np.append(narr, mixed_ch) + elif fw == 'caf': + dset_shape = (1, 3, h, w) + narr = np.fromstring( + rfb + gfb + bfb, count=(3 * h * w), dtype='float32') + for i in range(3 * h * w): + narr[i] /= 255.0 + if remove_existing: + subprocess.call(['rm', '-f', outfilename]) + with h5py.File(outfilename) as f: + # nnkit hdf5_import asserts to use IEEE_F32BE, which is >f4 in numpy + dset = f.require_dataset(inputname, dset_shape, dtype='>f4') + dset[0] = np.reshape(narr, dset_shape) + made_hdf = True + + if gen_binary and (not found_bin or remove_existing): + if fw == 'tfl' and made_hdf: + l = narr.tolist() + else: + reds = np.fromstring(rfb, count=(h * w), dtype='float32') + greens = np.fromstring(gfb, count=(h * w), dtype='float32') + blues = np.fromstring(bfb, count=(h * w), dtype='float32') + l = np.ndarray(shape=(0)) + mixed_ch = [] + for i in range(h * w): + mixed_ch += [ + reds[i] / 255.0, greens[i] / 255.0, blues[i] / 255.0 + ] + l = np.append(l, mixed_ch) + l = l.tolist() + with open(binoutfilename, 'wb') as out: + out.write(struct.pack('f' * len(l), *l)) + print(number, ': ' + testcase + ' Done') + else: + print(testcase, ' nothing to do') + else: + print(testcase, ' JPEG not found') + except: + print(testcase, " FAILED") +print('started at', ended.datetime.now()) diff --git a/compiler/nnc/utils/tflite_dot_dumper/sanity_check.cpp b/compiler/nnc/utils/tflite_dot_dumper/sanity_check.cpp index 2034825..b4d86e6 100644 --- a/compiler/nnc/utils/tflite_dot_dumper/sanity_check.cpp +++ b/compiler/nnc/utils/tflite_dot_dumper/sanity_check.cpp @@ -27,18 +27,22 @@ using namespace nnc; using namespace mir; using namespace nnc::cli; -int main(int argc, const char **argv) { +int main(int argc, const char **argv) +{ cli::CommandLine::getParser()->parseCommandLine(argc, argv, false); nnc::TfliteImporterPass importer{cli::inputFile}; - try { + try + { importer.import(); IrDotDumper dotDumper; auto g = importer.createIR(); g->accept(&dotDumper); dotDumper.writeDot(std::cout); - } catch (PassException &e) { + } + catch (PassException &e) + { std::cout << "Error: " << e.what() << std::endl; return -1; } diff --git a/compiler/nnc/utils/tflite_model_generator/ModelGenerator.cpp b/compiler/nnc/utils/tflite_model_generator/ModelGenerator.cpp index 99ceac4..fc42d79 100644 --- a/compiler/nnc/utils/tflite_model_generator/ModelGenerator.cpp +++ b/compiler/nnc/utils/tflite_model_generator/ModelGenerator.cpp @@ -26,7 +26,8 @@ using namespace modelgen; using namespace treebuilder; -int main(int argc, const char* argv[]) { +int main(int argc, const char *argv[]) +{ std::unique_ptr tree_builder(new TreeBuilder); auto tree = tree_builder->buildTree(); diff --git a/compiler/nnc/utils/tflite_model_generator/RandomModelBuilder.h b/compiler/nnc/utils/tflite_model_generator/RandomModelBuilder.h index bdcf948..b6659a0 100644 --- a/compiler/nnc/utils/tflite_model_generator/RandomModelBuilder.h +++ b/compiler/nnc/utils/tflite_model_generator/RandomModelBuilder.h @@ -24,11 +24,13 @@ #include "Tree.h" -namespace modelgen { +namespace modelgen +{ /** * @brief ModelSaver this class describes a common interface for saving model. */ -class ModelSaver { +class ModelSaver +{ public: ModelSaver() = default; virtual ~ModelSaver() = default; @@ -43,52 +45,42 @@ public: * @brief RandomModelBuilder this class describe a common interface for building * random neural network models. */ -class RandomModelBuilder { +class RandomModelBuilder +{ public: - /** * @brief constructor for RandomModelBuilder. * @details Be careful, opCreators's initializer list should save the order * from the OpCode enum. */ - RandomModelBuilder() : _operatorCounts{0}, _gen(_rd()), - _floatRand(std::numeric_limits::min(), - std::numeric_limits::max()), - _intRand(static_cast(OpCodes::opFirst), - static_cast(OpCodes::opLast)) { + RandomModelBuilder() + : _operatorCounts{0}, _gen(_rd()), + _floatRand(std::numeric_limits::min(), std::numeric_limits::max()), + _intRand(static_cast(OpCodes::opFirst), static_cast(OpCodes::opLast)) + { _opCreators[static_cast(OpCodes::opConv2d)] = - [this](treebuilder::Tree* t, treebuilder::Operation* op) { - createLayerCONV_2D(t, op); - }; - _opCreators[static_cast(OpCodes::opConcatenation)] = - [this](treebuilder::Tree* t, treebuilder::Operation* op) { - createLayerCONCATENATION(t, op); - }; - _opCreators[static_cast(OpCodes::opDepthwiseConv2d)] = - [this](treebuilder::Tree* t, treebuilder::Operation* op) { - createLayerDEPTHWISE_CONV_2D(t, op); - }; - _opCreators[static_cast(OpCodes::opOpMaxPool2d)] = - [this](treebuilder::Tree* t, treebuilder::Operation* op) { - createLayerX_POOL_2D(t, op, OpCodes::opOpMaxPool2d); - }; - _opCreators[static_cast(OpCodes::opAveragePool2d)] = - [this](treebuilder::Tree* t, treebuilder::Operation* op) { - createLayerX_POOL_2D(t, op, OpCodes::opAveragePool2d); - }; + [this](treebuilder::Tree *t, treebuilder::Operation *op) { createLayerCONV_2D(t, op); }; + _opCreators[static_cast(OpCodes::opConcatenation)] = [this]( + treebuilder::Tree *t, treebuilder::Operation *op) { createLayerCONCATENATION(t, op); }; + _opCreators[static_cast(OpCodes::opDepthwiseConv2d)] = [this]( + treebuilder::Tree *t, treebuilder::Operation *op) { createLayerDEPTHWISE_CONV_2D(t, op); }; + _opCreators[static_cast(OpCodes::opOpMaxPool2d)] = [this](treebuilder::Tree *t, + treebuilder::Operation *op) { + createLayerX_POOL_2D(t, op, OpCodes::opOpMaxPool2d); + }; + _opCreators[static_cast(OpCodes::opAveragePool2d)] = [this](treebuilder::Tree *t, + treebuilder::Operation *op) { + createLayerX_POOL_2D(t, op, OpCodes::opAveragePool2d); + }; _opCreators[static_cast(OpCodes::opSoftmax)] = - [this](treebuilder::Tree* t, treebuilder::Operation* op) { - createLayerSOFTMAX(t, op); - }; - _opCreators[static_cast(OpCodes::opFullyConnected)] = - [this](treebuilder::Tree* t, treebuilder::Operation* op) { - createLayerFULLY_CONNECTED(t, op); - }; + [this](treebuilder::Tree *t, treebuilder::Operation *op) { createLayerSOFTMAX(t, op); }; + _opCreators[static_cast(OpCodes::opFullyConnected)] = [this]( + treebuilder::Tree *t, treebuilder::Operation *op) { createLayerFULLY_CONNECTED(t, op); }; }; virtual ~RandomModelBuilder() = default; - virtual void convertTreeToModel(treebuilder::Tree* t) = 0; + virtual void convertTreeToModel(treebuilder::Tree *t) = 0; /** * @brief getModelSaver does create unique_ptr to ModelSaver. @@ -100,23 +92,23 @@ protected: /** * @Brief createInput does add input tensor to model. */ - virtual void createInput(treebuilder::Tree* t) = 0; + virtual void createInput(treebuilder::Tree *t) = 0; /** * @brief addOperator does add a new layer to model. */ - virtual void addOperator(treebuilder::Tree* t, treebuilder::Operation* op) = 0; + virtual void addOperator(treebuilder::Tree *t, treebuilder::Operation *op) = 0; /** * @brief createLayerXXX are creator for operators. * @param input_tensor_id is id of input tensor. */ - virtual void createLayerCONV_2D(treebuilder::Tree*, treebuilder::Operation*) = 0; - virtual void createLayerCONCATENATION(treebuilder::Tree* t, treebuilder::Operation* op) = 0; - virtual void createLayerDEPTHWISE_CONV_2D(treebuilder::Tree* t, treebuilder::Operation* op) = 0; - virtual void createLayerX_POOL_2D(treebuilder::Tree* t, treebuilder::Operation* op, + virtual void createLayerCONV_2D(treebuilder::Tree *, treebuilder::Operation *) = 0; + virtual void createLayerCONCATENATION(treebuilder::Tree *t, treebuilder::Operation *op) = 0; + virtual void createLayerDEPTHWISE_CONV_2D(treebuilder::Tree *t, treebuilder::Operation *op) = 0; + virtual void createLayerX_POOL_2D(treebuilder::Tree *t, treebuilder::Operation *op, OpCodes opcode) = 0; - virtual void createLayerSOFTMAX(treebuilder::Tree* t, treebuilder::Operation* op) = 0; - virtual void createLayerFULLY_CONNECTED(treebuilder::Tree* t, treebuilder::Operation* op) = 0; + virtual void createLayerSOFTMAX(treebuilder::Tree *t, treebuilder::Operation *op) = 0; + virtual void createLayerFULLY_CONNECTED(treebuilder::Tree *t, treebuilder::Operation *op) = 0; /** * @brief opCreators this array contains a lambda with call of method @@ -125,8 +117,8 @@ protected: * like follow: opCreators[OpCodes::opCount] * For example: opCreators[OpCodes::opConv2d](0) -- will lead to call createLayerCONV_2D method. */ - std::function _opCreators[static_cast(OpCodes::opCount)]; + std::function + _opCreators[static_cast(OpCodes::opCount)]; /** * @brief operatorCounts this array contains amount of used operators in generated model. * @details For example: operatorCounts[Op_CONV_2D] -- amount of used 2D convolution operators. diff --git a/compiler/nnc/utils/tflite_model_generator/TFLiteRandomModelBuilder.cpp b/compiler/nnc/utils/tflite_model_generator/TFLiteRandomModelBuilder.cpp index 442b9ec..4347d2c 100644 --- a/compiler/nnc/utils/tflite_model_generator/TFLiteRandomModelBuilder.cpp +++ b/compiler/nnc/utils/tflite_model_generator/TFLiteRandomModelBuilder.cpp @@ -19,11 +19,12 @@ #include "TFLiteRandomModelBuilder.h" -namespace modelgen { -static const char* modelFileOut = "model.tflite"; +namespace modelgen +{ +static const char *modelFileOut = "model.tflite"; static const int notInitialized = -1; -static const char* const opNames[] = { +static const char *const opNames[] = { #define DEF_OPERATOR(Name, OpCode, TFLiteOpCode, CreatorFunc) Name, #include "Operator.def" #undef DEF_OPERATOR @@ -35,7 +36,8 @@ static const tflite::BuiltinOperator internalOpCode2TFLiteOpCode[]{ #undef DEF_OPERATOR }; -void TFLiteModelSaver::saveModel() { +void TFLiteModelSaver::saveModel() +{ auto m = tflite::Model::Pack(_flatBufferBuilder, _model.get()); tflite::FinishModelBuffer(_flatBufferBuilder, m); @@ -50,27 +52,31 @@ void TFLiteModelSaver::saveModel() { fclose(f); } -TFLiteRandomModelBuilder::TFLiteRandomModelBuilder() : RandomModelBuilder(), - _model(new ModelT()) { +TFLiteRandomModelBuilder::TFLiteRandomModelBuilder() : RandomModelBuilder(), _model(new ModelT()) +{ std::fill_n(_mapOperatorCode, static_cast(OpCodes::opCount), notInitialized); } -void TFLiteRandomModelBuilder::convertTreeToModel(treebuilder::Tree* t) { +void TFLiteRandomModelBuilder::convertTreeToModel(treebuilder::Tree *t) +{ createInput(t); - for (auto& op : t->opList) { + for (auto &op : t->opList) + { addOperator(t, op.get()); } } -std::unique_ptr TFLiteRandomModelBuilder::createModelSaver() { +std::unique_ptr TFLiteRandomModelBuilder::createModelSaver() +{ return std::unique_ptr(new TFLiteModelSaver(std::move(_model))); } /** * @todo Add support several inputs. */ -void TFLiteRandomModelBuilder::createInput(treebuilder::Tree* t) { +void TFLiteRandomModelBuilder::createInput(treebuilder::Tree *t) +{ assert(_model->subgraphs.empty() && "Subgraph is already created"); std::unique_ptr subgraph(new SubGraphT); @@ -85,7 +91,8 @@ void TFLiteRandomModelBuilder::createInput(treebuilder::Tree* t) { _model->version = 3; } -void TFLiteRandomModelBuilder::addOperator(treebuilder::Tree* t, treebuilder::Operation* op) { +void TFLiteRandomModelBuilder::addOperator(treebuilder::Tree *t, treebuilder::Operation *op) +{ assert(!_model->subgraphs.empty() && "Subgraph is not created"); std::cout << "Add operator [" << opNames[static_cast(op->opcode)] << "] on the level [ " @@ -94,8 +101,8 @@ void TFLiteRandomModelBuilder::addOperator(treebuilder::Tree* t, treebuilder::Op _model->subgraphs[0]->outputs[0] = (*_model->subgraphs[0]->operators.rbegin())->outputs[0]; } -void TFLiteRandomModelBuilder::createLayerCONV_2D(treebuilder::Tree* t, - treebuilder::Operation* op) { +void TFLiteRandomModelBuilder::createLayerCONV_2D(treebuilder::Tree *t, treebuilder::Operation *op) +{ std::string output_name(opNames[static_cast(OpCodes::opConv2d)]); output_name += "_" + std::to_string(_operatorCounts[static_cast(OpCodes::opConv2d)]); auto operator_ptr = createEmptyOperator(op); @@ -104,8 +111,8 @@ void TFLiteRandomModelBuilder::createLayerCONV_2D(treebuilder::Tree* t, auto kernel_ptr = createTensorWthBuffer(op->kernelShape, "Kernel"); auto bias_ptr = createTensorWthBuffer({op->outputShape[3]}, "bias"); - auto input_tensor_id = op->levelOwner == 0 ? _operandTree2tensor[0] : - _operandTree2tensor[t->inputCnt + op->inputs[0]]; + auto input_tensor_id = op->levelOwner == 0 ? _operandTree2tensor[0] + : _operandTree2tensor[t->inputCnt + op->inputs[0]]; operator_ptr->inputs.push_back(input_tensor_id); operator_ptr->inputs.push_back(static_cast(_model->subgraphs[0]->tensors.size())); @@ -122,25 +129,27 @@ void TFLiteRandomModelBuilder::createLayerCONV_2D(treebuilder::Tree* t, auto conv2D_opt = operator_ptr->builtin_options.AsConv2DOptions(); conv2D_opt->stride_w = conv2D_opt->stride_h = 1; conv2D_opt->fused_activation_function = - tflite::ActivationFunctionType::ActivationFunctionType_RELU6; + tflite::ActivationFunctionType::ActivationFunctionType_RELU6; _model->subgraphs[0]->operators.push_back(std::move(operator_ptr)); } -void TFLiteRandomModelBuilder::createLayerCONCATENATION(treebuilder::Tree* t, - treebuilder::Operation* op) { +void TFLiteRandomModelBuilder::createLayerCONCATENATION(treebuilder::Tree *t, + treebuilder::Operation *op) +{ std::string output_name(opNames[static_cast(OpCodes::opConcatenation)]); - output_name += "_" + - std::to_string(_operatorCounts[static_cast(OpCodes::opConcatenation)]); + output_name += + "_" + std::to_string(_operatorCounts[static_cast(OpCodes::opConcatenation)]); auto operator_ptr = createEmptyOperator(op); auto out_tensor_ptr = createEmptyTensor(op->outputShape, output_name.c_str()); std::cout << "Concatination inputs [ "; - for (auto it : op->inputs) { + for (auto it : op->inputs) + { std::cout << it << "/"; - auto input_tensor_id = op->levelOwner == 0 ? _operandTree2tensor[0] : - _operandTree2tensor[t->inputCnt + it]; + auto input_tensor_id = + op->levelOwner == 0 ? _operandTree2tensor[0] : _operandTree2tensor[t->inputCnt + it]; std::cout << input_tensor_id << " "; operator_ptr->inputs.push_back(input_tensor_id); } @@ -154,31 +163,33 @@ void TFLiteRandomModelBuilder::createLayerCONCATENATION(treebuilder::Tree* t, operator_ptr->builtin_options.Set(tflite::ConcatenationOptionsT()); auto concat_opt = operator_ptr->builtin_options.AsConcatenationOptions(); concat_opt->fused_activation_function = - tflite::ActivationFunctionType::ActivationFunctionType_RELU6; + tflite::ActivationFunctionType::ActivationFunctionType_RELU6; concat_opt->axis = 0; - for (auto it : op->inputShape) { + for (auto it : op->inputShape) + { if (it == -1) - break ; + break; concat_opt->axis++; } _model->subgraphs[0]->operators.push_back(std::move(operator_ptr)); } -void TFLiteRandomModelBuilder::createLayerDEPTHWISE_CONV_2D(treebuilder::Tree* t, - treebuilder::Operation* op) { +void TFLiteRandomModelBuilder::createLayerDEPTHWISE_CONV_2D(treebuilder::Tree *t, + treebuilder::Operation *op) +{ std::string output_name(opNames[static_cast(OpCodes::opDepthwiseConv2d)]); - output_name += "_" + - std::to_string(_operatorCounts[static_cast(OpCodes::opDepthwiseConv2d)]); + output_name += + "_" + std::to_string(_operatorCounts[static_cast(OpCodes::opDepthwiseConv2d)]); auto operator_ptr = createEmptyOperator(op); auto out_tensor_ptr = createEmptyTensor(op->outputShape, output_name.c_str()); auto kernel_ptr = createTensorWthBuffer(op->kernelShape, "Kernel"); auto bias_ptr = createTensorWthBuffer({op->outputShape[3]}, "bias"); - auto input_tensor_id = op->levelOwner == 0 ? _operandTree2tensor[0] : - _operandTree2tensor[t->inputCnt + op->inputs[0]]; + auto input_tensor_id = op->levelOwner == 0 ? _operandTree2tensor[0] + : _operandTree2tensor[t->inputCnt + op->inputs[0]]; operator_ptr->inputs.push_back(input_tensor_id); operator_ptr->inputs.push_back(static_cast(_model->subgraphs[0]->tensors.size())); @@ -196,22 +207,22 @@ void TFLiteRandomModelBuilder::createLayerDEPTHWISE_CONV_2D(treebuilder::Tree* t depthwise_conv2d_opt->stride_w = depthwise_conv2d_opt->stride_h = 1; depthwise_conv2d_opt->depth_multiplier = 1; depthwise_conv2d_opt->fused_activation_function = - tflite::ActivationFunctionType::ActivationFunctionType_RELU6; + tflite::ActivationFunctionType::ActivationFunctionType_RELU6; _model->subgraphs[0]->operators.push_back(std::move(operator_ptr)); } -void TFLiteRandomModelBuilder::createLayerX_POOL_2D(treebuilder::Tree* t, - treebuilder::Operation* op, OpCodes opcode) { +void TFLiteRandomModelBuilder::createLayerX_POOL_2D(treebuilder::Tree *t, + treebuilder::Operation *op, OpCodes opcode) +{ std::string output_name(opNames[static_cast(opcode)]); - output_name += "_" + - std::to_string(_operatorCounts[static_cast(opcode)]); + output_name += "_" + std::to_string(_operatorCounts[static_cast(opcode)]); auto operator_ptr = createEmptyOperator(op); auto out_tensor_ptr = createEmptyTensor(op->outputShape, output_name.c_str()); - auto input_tensor_id = op->levelOwner == 0 ? _operandTree2tensor[0] : - _operandTree2tensor[t->inputCnt + op->inputs[0]]; + auto input_tensor_id = op->levelOwner == 0 ? _operandTree2tensor[0] + : _operandTree2tensor[t->inputCnt + op->inputs[0]]; operator_ptr->inputs.push_back(input_tensor_id); auto output_tensor_id = static_cast(_model->subgraphs[0]->tensors.size()); @@ -230,17 +241,16 @@ void TFLiteRandomModelBuilder::createLayerX_POOL_2D(treebuilder::Tree* t, _model->subgraphs[0]->operators.push_back(std::move(operator_ptr)); } -void TFLiteRandomModelBuilder::createLayerSOFTMAX(treebuilder::Tree* t, - treebuilder::Operation* op) { +void TFLiteRandomModelBuilder::createLayerSOFTMAX(treebuilder::Tree *t, treebuilder::Operation *op) +{ std::string output_name(opNames[static_cast(OpCodes::opSoftmax)]); - output_name += "_" + - std::to_string(_operatorCounts[static_cast(OpCodes::opSoftmax)]); + output_name += "_" + std::to_string(_operatorCounts[static_cast(OpCodes::opSoftmax)]); auto operator_ptr = createEmptyOperator(op); auto out_tensor_ptr = createEmptyTensor(op->outputShape, output_name.c_str()); - auto input_tensor_id = op->levelOwner == 0 ? _operandTree2tensor[0] : - _operandTree2tensor[t->inputCnt + op->inputs[0]]; + auto input_tensor_id = op->levelOwner == 0 ? _operandTree2tensor[0] + : _operandTree2tensor[t->inputCnt + op->inputs[0]]; operator_ptr->inputs.push_back(input_tensor_id); auto output_tensor_id = static_cast(_model->subgraphs[0]->tensors.size()); @@ -255,19 +265,20 @@ void TFLiteRandomModelBuilder::createLayerSOFTMAX(treebuilder::Tree* t, _model->subgraphs[0]->operators.push_back(std::move(operator_ptr)); } -void TFLiteRandomModelBuilder::createLayerFULLY_CONNECTED(treebuilder::Tree* t, - treebuilder::Operation* op) { +void TFLiteRandomModelBuilder::createLayerFULLY_CONNECTED(treebuilder::Tree *t, + treebuilder::Operation *op) +{ std::string output_name(opNames[static_cast(OpCodes::opFullyConnected)]); - output_name += "_" + - std::to_string(_operatorCounts[static_cast(OpCodes::opFullyConnected)]); + output_name += + "_" + std::to_string(_operatorCounts[static_cast(OpCodes::opFullyConnected)]); auto operator_ptr = createEmptyOperator(op); auto out_tensor_ptr = createEmptyTensor(op->outputShape, output_name.c_str()); auto kernel_ptr = createTensorWthBuffer(op->kernelShape, "Kernel"); auto bias_ptr = createTensorWthBuffer({op->outputShape[3]}, "bias"); - auto input_tensor_id = op->levelOwner == 0 ? _operandTree2tensor[0] : - _operandTree2tensor[t->inputCnt + op->inputs[0]]; + auto input_tensor_id = op->levelOwner == 0 ? _operandTree2tensor[0] + : _operandTree2tensor[t->inputCnt + op->inputs[0]]; operator_ptr->inputs.push_back(input_tensor_id); operator_ptr->inputs.push_back(static_cast(_model->subgraphs[0]->tensors.size())); @@ -283,14 +294,14 @@ void TFLiteRandomModelBuilder::createLayerFULLY_CONNECTED(treebuilder::Tree* t, operator_ptr->builtin_options.Set(tflite::FullyConnectedOptionsT()); auto fullcon_opt = operator_ptr->builtin_options.AsFullyConnectedOptions(); fullcon_opt->fused_activation_function = - tflite::ActivationFunctionType::ActivationFunctionType_RELU6; + tflite::ActivationFunctionType::ActivationFunctionType_RELU6; _model->subgraphs[0]->operators.push_back(std::move(operator_ptr)); } std::unique_ptr -TFLiteRandomModelBuilder::createEmptyTensor(const std::vector& shape, - const char* name) { +TFLiteRandomModelBuilder::createEmptyTensor(const std::vector &shape, const char *name) +{ auto tensor_ptr = std::unique_ptr(new TensorT); tensor_ptr->type = tflite::TensorType_FLOAT32; @@ -303,32 +314,35 @@ TFLiteRandomModelBuilder::createEmptyTensor(const std::vector& shape, } std::unique_ptr -TFLiteRandomModelBuilder::createTensorWthBuffer(const std::vector& shape, - const char* name) { +TFLiteRandomModelBuilder::createTensorWthBuffer(const std::vector &shape, const char *name) +{ auto tensor_ptr = createEmptyTensor(shape, name); size_t buffer_size = 1; - for (auto s : shape) { + for (auto s : shape) + { buffer_size *= s; } buffer_size *= sizeof(float); _model->buffers[tensor_ptr->buffer]->data.resize(buffer_size); - for (size_t i = 0; i < buffer_size; i += sizeof(float)) { + for (size_t i = 0; i < buffer_size; i += sizeof(float)) + { float val = _floatRand(_gen); memcpy(_model->buffers[tensor_ptr->buffer]->data.data() + i, &val, sizeof(float)); } return tensor_ptr; } -std::unique_ptr -TFLiteRandomModelBuilder::createEmptyOperator(treebuilder::Operation* op) { +std::unique_ptr TFLiteRandomModelBuilder::createEmptyOperator(treebuilder::Operation *op) +{ auto operator_ptr = std::unique_ptr(new OperatorT); auto opcode_id = _mapOperatorCode[static_cast(op->opcode)]; auto tflite_opcode = internalOpCode2TFLiteOpCode[static_cast(op->opcode)]; - if (opcode_id == notInitialized) { + if (opcode_id == notInitialized) + { auto opcode_ptr = std::unique_ptr(new OperatorCodeT); opcode_ptr->builtin_code = tflite_opcode; opcode_ptr->custom_code = tflite::EnumNamesBuiltinOperator()[tflite_opcode]; diff --git a/compiler/nnc/utils/tflite_model_generator/TFLiteRandomModelBuilder.h b/compiler/nnc/utils/tflite_model_generator/TFLiteRandomModelBuilder.h index 826b22a..38ff7bd 100644 --- a/compiler/nnc/utils/tflite_model_generator/TFLiteRandomModelBuilder.h +++ b/compiler/nnc/utils/tflite_model_generator/TFLiteRandomModelBuilder.h @@ -24,21 +24,24 @@ #include "RandomModelBuilder.h" #include "schema_generated.h" -namespace modelgen { +namespace modelgen +{ using namespace tflite; /** * @brief TFLiteModelSaver contains the unique_ptr to model and does convertation of model * to FlatBuffer format and it's saving. */ -class TFLiteModelSaver : public ModelSaver { +class TFLiteModelSaver : public ModelSaver +{ public: TFLiteModelSaver() = default; ~TFLiteModelSaver() override = default; - TFLiteModelSaver(std::unique_ptr&& m) : ModelSaver(), _model(std::move(m)) {} + TFLiteModelSaver(std::unique_ptr &&m) : ModelSaver(), _model(std::move(m)) {} void saveModel() override; + private: flatbuffers::FlatBufferBuilder _flatBufferBuilder; std::unique_ptr _model; @@ -48,27 +51,30 @@ private: * @brief TFLiteRandomModelBuilder does build random TFLiteModel * and gives unique_ptr to ModelSaver for export it to file. */ -class TFLiteRandomModelBuilder : public RandomModelBuilder { +class TFLiteRandomModelBuilder : public RandomModelBuilder +{ public: TFLiteRandomModelBuilder(); ~TFLiteRandomModelBuilder() override = default; - void convertTreeToModel(treebuilder::Tree* t) override; + void convertTreeToModel(treebuilder::Tree *t) override; std::unique_ptr createModelSaver() override; + protected: - void createInput(treebuilder::Tree* t) override; - void addOperator(treebuilder::Tree* t, treebuilder::Operation* op) override; + void createInput(treebuilder::Tree *t) override; + void addOperator(treebuilder::Tree *t, treebuilder::Operation *op) override; /** * Operations: */ - void createLayerCONV_2D(treebuilder::Tree* t, treebuilder::Operation* op) override; - void createLayerCONCATENATION(treebuilder::Tree* t, treebuilder::Operation* op) override; - void createLayerDEPTHWISE_CONV_2D(treebuilder::Tree* t, treebuilder::Operation* op) override; - void createLayerX_POOL_2D(treebuilder::Tree* t, treebuilder::Operation* op, + void createLayerCONV_2D(treebuilder::Tree *t, treebuilder::Operation *op) override; + void createLayerCONCATENATION(treebuilder::Tree *t, treebuilder::Operation *op) override; + void createLayerDEPTHWISE_CONV_2D(treebuilder::Tree *t, treebuilder::Operation *op) override; + void createLayerX_POOL_2D(treebuilder::Tree *t, treebuilder::Operation *op, OpCodes opcode) override; - void createLayerSOFTMAX(treebuilder::Tree* t, treebuilder::Operation* op) override; - void createLayerFULLY_CONNECTED(treebuilder::Tree* t, treebuilder::Operation* op) override; + void createLayerSOFTMAX(treebuilder::Tree *t, treebuilder::Operation *op) override; + void createLayerFULLY_CONNECTED(treebuilder::Tree *t, treebuilder::Operation *op) override; + private: /** * @brief createEmptyTensor does create tensor without buffer @@ -77,8 +83,7 @@ private: * @param name is a name of tensor. * @return unique_ptr to created tensor. */ - std::unique_ptr createEmptyTensor(const std::vector& shape, - const char* name); + std::unique_ptr createEmptyTensor(const std::vector &shape, const char *name); /** * @brief createTensorWthBuffer does create tensor with buffer * and add it to tensors array of SubGraphT. @@ -86,15 +91,15 @@ private: * @param name is a name of tensor. * @return unique_ptr to created tensor. */ - std::unique_ptr createTensorWthBuffer(const std::vector& shape, - const char* name); + std::unique_ptr createTensorWthBuffer(const std::vector &shape, + const char *name); /** * @brief createEmptyOperator does create operator without tensors and * add operator to operators array of SubGraphT * @param opcode is operator's code. * @return unique_ptr to created operator. */ - std::unique_ptr createEmptyOperator(treebuilder::Operation* op); + std::unique_ptr createEmptyOperator(treebuilder::Operation *op); std::unique_ptr _model; /** diff --git a/compiler/nnc/utils/tflite_model_generator/Tree.cpp b/compiler/nnc/utils/tflite_model_generator/Tree.cpp index e9bdd1d..79620ba 100644 --- a/compiler/nnc/utils/tflite_model_generator/Tree.cpp +++ b/compiler/nnc/utils/tflite_model_generator/Tree.cpp @@ -19,8 +19,10 @@ #include "Tree.h" -namespace modelgen { -namespace treebuilder { +namespace modelgen +{ +namespace treebuilder +{ static constexpr int levelsMin = 1; static constexpr int levelsMax = 15; @@ -34,9 +36,10 @@ static constexpr int depthwiseConv2dMultiply = 4; static constexpr int fullyConnectedMaxWeight = 8; static constexpr int fullyConnectedKernelDim = 2; -TreeBuilder::TreeBuilder() : _gen(_rd()) { } +TreeBuilder::TreeBuilder() : _gen(_rd()) {} -std::unique_ptr TreeBuilder::buildTree() { +std::unique_ptr TreeBuilder::buildTree() +{ std::uniform_int_distribution int_rand(levelsMin, levelsMax); auto t = std::unique_ptr(new Tree); t->inputCnt = 1; @@ -44,7 +47,8 @@ std::unique_ptr TreeBuilder::buildTree() { initTree(t.get()); std::cout << "Build " << t->hTree << " levels in tree" << std::endl; - for (int i = 1; i < t->hTree; i++) { + for (int i = 1; i < t->hTree; i++) + { buildLevel(t.get()); } @@ -54,7 +58,8 @@ std::unique_ptr TreeBuilder::buildTree() { return t; } -void TreeBuilder::buildLevel(Tree* t) { +void TreeBuilder::buildLevel(Tree *t) +{ std::uniform_int_distribution int_rand(widthMin, widthMax); auto levelId = t->widthLevel.size(); auto levelWidth = int_rand(_gen); @@ -62,13 +67,15 @@ void TreeBuilder::buildLevel(Tree* t) { t->beginLevel.push_back(static_cast(t->opList.size())); t->endLevel.push_back(static_cast(t->opList.size() + levelWidth - 1)); - for (int32_t i = 0; i < levelWidth; i++) { + for (int32_t i = 0; i < levelWidth; i++) + { auto op = std::unique_ptr(new Operation); op->levelOwner = levelId; /** * If the operation was not created, then repeat the creation. */ - if (!buildSketchOperation(t, op.get())) { + if (!buildSketchOperation(t, op.get())) + { i--; continue; } @@ -76,7 +83,8 @@ void TreeBuilder::buildLevel(Tree* t) { } } -void TreeBuilder::initTree(Tree* t) { +void TreeBuilder::initTree(Tree *t) +{ std::uniform_int_distribution int_rand(shapeMin, shapeMax); std::cout << "Build first level in tree" << std::endl; @@ -88,14 +96,17 @@ void TreeBuilder::initTree(Tree* t) { t->inputShapeTree = {1, x, y, z}; std::cout << "Initialize first level with width = [ " << t->widthLevel[0] << " ]" - << " and shape [ 1" << " " << x << " " << y << " " << z << " ]" << std::endl; - for (int32_t i = 0; i < t->widthLevel[0]; i++) { + << " and shape [ 1" + << " " << x << " " << y << " " << z << " ]" << std::endl; + for (int32_t i = 0; i < t->widthLevel[0]; i++) + { auto op = std::unique_ptr(new Operation); op->levelOwner = 0; /** * If the operation was not created, then repeat the creation. */ - if (!buildSketchOperation(t, op.get())) { + if (!buildSketchOperation(t, op.get())) + { i--; continue; } @@ -103,12 +114,14 @@ void TreeBuilder::initTree(Tree* t) { } } -bool TreeBuilder::buildSketchOperation(Tree* t, Operation* op) { +bool TreeBuilder::buildSketchOperation(Tree *t, Operation *op) +{ std::uniform_int_distribution opcode_rand(static_cast(OpCodes::opFirst), static_cast(OpCodes::opLast)); op->opcode = static_cast(opcode_rand(_gen)); - switch(op->opcode) { + switch (op->opcode) + { case OpCodes::opConv2d: buildSketchConv2D(t, op); break; @@ -130,7 +143,8 @@ bool TreeBuilder::buildSketchOperation(Tree* t, Operation* op) { * Currently, we can create fullyconnected operation only on last level. * @todo fix it. */ - if (t->beginLevel.size() != static_cast(t->hTree)) { + if (t->beginLevel.size() != static_cast(t->hTree)) + { return false; } @@ -143,13 +157,15 @@ bool TreeBuilder::buildSketchOperation(Tree* t, Operation* op) { return true; } -void TreeBuilder::buildSketchConv2D(Tree* t, Operation* op) { +void TreeBuilder::buildSketchConv2D(Tree *t, Operation *op) +{ std::uniform_int_distribution int_rand(0, INT32_MAX); - if (t->beginLevel.size() == 1) { + if (t->beginLevel.size() == 1) + { op->inputShape = t->inputShapeTree; buildSketchConv2DForShape(op->inputShape, op); - return ; + return; } auto levelId = int_rand(_gen) % (t->beginLevel.size() - 1); @@ -163,23 +179,26 @@ void TreeBuilder::buildSketchConv2D(Tree* t, Operation* op) { buildSketchConv2DForShape(op->inputShape, op); } -void TreeBuilder::buildSketchConcat(Tree* t, Operation* op) { +void TreeBuilder::buildSketchConcat(Tree *t, Operation *op) +{ std::uniform_int_distribution int_rand(2, INT32_MAX); auto axis = 1 + (int_rand(_gen) + 3) % 3; auto input_cnt = concatCntInputsMin + int_rand(_gen) % concatCntInputsMax; /* Special case if there are only one level (input to neural network) */ - if (t->beginLevel.size() == 1) { + if (t->beginLevel.size() == 1) + { op->inputShape = t->inputShapeTree; op->outputShape = op->inputShape; - for (int i = 0; i < input_cnt; i++) { + for (int i = 0; i < input_cnt; i++) + { op->inputs.push_back(-1); /* -1 means that it is needed to specify amount inputs * on the first level where input tensor for operation * is a input tensor for neural network. */ addConcatInput(op->inputShape, axis, op); } op->inputShape[axis] = -1; /* specify a dimension for concatenation. */ - return ; + return; } /* Select the first operand */ @@ -193,7 +212,8 @@ void TreeBuilder::buildSketchConcat(Tree* t, Operation* op) { op->outputShape = op->inputShape; std::vector shape = op->inputShape; shape[axis] = -1; - for (int i = 0; i < input_cnt; i++) { + for (int i = 0; i < input_cnt; i++) + { opId = lookupConsistentOutput(t, op, shape, t->beginLevel.size() - 1); op->inputs.push_back(opId); addConcatInput(t->opList[opId]->outputShape, axis, op); @@ -202,7 +222,8 @@ void TreeBuilder::buildSketchConcat(Tree* t, Operation* op) { op->inputShape[axis] = -1; /* specify a dimension for concatenation. */ } -void TreeBuilder::buildSketchDepthwiseConv2D(Tree* t, Operation* op) { +void TreeBuilder::buildSketchDepthwiseConv2D(Tree *t, Operation *op) +{ std::uniform_int_distribution int_rand(1, INT32_MAX); /** * Currently, on the stage of building arbitrary tree it is enough @@ -221,18 +242,20 @@ void TreeBuilder::buildSketchDepthwiseConv2D(Tree* t, Operation* op) { op->outputShape[3] = op->kernelShape[0] * op->kernelShape[3]; } -void TreeBuilder::buildSketchPooling(Tree* t, Operation* op) { +void TreeBuilder::buildSketchPooling(Tree *t, Operation *op) +{ std::uniform_int_distribution int_rand(2, INT32_MAX); - if (t->beginLevel.size() == 1) { + if (t->beginLevel.size() == 1) + { op->inputShape = t->inputShapeTree; op->outputShape = op->inputShape; - return ; + return; } auto levelId = int_rand(_gen) % (t->beginLevel.size() - 1); auto opId = t->beginLevel[levelId] + (int_rand(_gen) % t->widthLevel[levelId]); - + std::cout << "input level [ " << levelId << " ] operation id [ " << opId << " ]" << std::endl; op->inputs.push_back(opId); @@ -241,7 +264,8 @@ void TreeBuilder::buildSketchPooling(Tree* t, Operation* op) { op->outputShape = op->inputShape; } -void TreeBuilder::buildSketchSoftmax(Tree* t, Operation* op) { +void TreeBuilder::buildSketchSoftmax(Tree *t, Operation *op) +{ /** * We need only select input node, the output shape will be same as input. * That is why we use pooling's builder. @@ -249,7 +273,8 @@ void TreeBuilder::buildSketchSoftmax(Tree* t, Operation* op) { buildSketchPooling(t, op); } -void TreeBuilder::buildSketchFullyConnected(Tree* t, Operation* op) { +void TreeBuilder::buildSketchFullyConnected(Tree *t, Operation *op) +{ std::uniform_int_distribution int_rand(2, fullyConnectedMaxWeight); /** * 1. Select a input form previous nodes by means of buildSketchPooling @@ -261,8 +286,8 @@ void TreeBuilder::buildSketchFullyConnected(Tree* t, Operation* op) { */ op->kernelShape.resize(fullyConnectedKernelDim); op->kernelShape[0] = int_rand(_gen); - op->kernelShape[1] = op->inputShape[0] * op->inputShape[1] * - op->inputShape[2] * op->inputShape[3]; + op->kernelShape[1] = + op->inputShape[0] * op->inputShape[1] * op->inputShape[2] * op->inputShape[3]; op->outputShape.resize(2); op->outputShape[0] = op->kernelShape[0]; @@ -271,11 +296,15 @@ void TreeBuilder::buildSketchFullyConnected(Tree* t, Operation* op) { // =========== private =========== -int32_t TreeBuilder::lookupConsistentOutput(Tree* t, Operation* op, std::vector& shape, - int32_t until_level) { - for (int i =0, j = 0; i < t->beginLevel[until_level]; i++) { - for (j = 0; j < 4; j++) { - if (shape[j] != t->opList[i]->outputShape[j] && shape[j] != -1) { +int32_t TreeBuilder::lookupConsistentOutput(Tree *t, Operation *op, std::vector &shape, + int32_t until_level) +{ + for (int i = 0, j = 0; i < t->beginLevel[until_level]; i++) + { + for (j = 0; j < 4; j++) + { + if (shape[j] != t->opList[i]->outputShape[j] && shape[j] != -1) + { j = 0; break; } @@ -292,20 +321,24 @@ int32_t TreeBuilder::lookupConsistentOutput(Tree* t, Operation* op, std::vector< * \ / * op */ - const Operation* y = t->opList[op->inputs[0]].get(); + const Operation *y = t->opList[op->inputs[0]].get(); std::unique_ptr new_op = std::unique_ptr(new Operation(*y)); /* * reindex operations */ auto inser_pos = t->beginLevel[y->levelOwner]; - for (auto& in : op->inputs) { + for (auto &in : op->inputs) + { if (in >= inser_pos) in++; } - for (int i = inser_pos; i < static_cast(t->opList.size()); i++) { - for (auto& in : t->opList[i]->inputs) { - if (in >= inser_pos) { + for (int i = inser_pos; i < static_cast(t->opList.size()); i++) + { + for (auto &in : t->opList[i]->inputs) + { + if (in >= inser_pos) + { in++; } } @@ -313,7 +346,8 @@ int32_t TreeBuilder::lookupConsistentOutput(Tree* t, Operation* op, std::vector< t->endLevel[y->levelOwner]++; t->widthLevel[y->levelOwner]++; - for (int i = y->levelOwner + 1; i < static_cast(t->beginLevel.size()); i++) { + for (int i = y->levelOwner + 1; i < static_cast(t->beginLevel.size()); i++) + { t->beginLevel[i]++; t->endLevel[i]++; } @@ -322,7 +356,8 @@ int32_t TreeBuilder::lookupConsistentOutput(Tree* t, Operation* op, std::vector< return inser_pos; } -void TreeBuilder::buildSketchConv2DForShape(std::vector& input_shape, Operation* op) { +void TreeBuilder::buildSketchConv2DForShape(std::vector &input_shape, Operation *op) +{ std::uniform_int_distribution int_rand(shapeMin, shapeMax); /* out channels */ @@ -340,8 +375,10 @@ void TreeBuilder::buildSketchConv2DForShape(std::vector& input_shape, O std::cout << " ]" << std::endl; } -void TreeBuilder::addConcatInput(std::vector& input_shape, int32_t axis, Operation* op) { - for (int i = 0 ; i < 4; i++) { +void TreeBuilder::addConcatInput(std::vector &input_shape, int32_t axis, Operation *op) +{ + for (int i = 0; i < 4; i++) + { if (input_shape[i] != op->inputShape[i] && i != axis) assert(false && "Not consistency input shapes\n"); } diff --git a/compiler/nnc/utils/tflite_model_generator/Tree.h b/compiler/nnc/utils/tflite_model_generator/Tree.h index a032b95..1d4f00d 100644 --- a/compiler/nnc/utils/tflite_model_generator/Tree.h +++ b/compiler/nnc/utils/tflite_model_generator/Tree.h @@ -24,9 +24,11 @@ #include -namespace modelgen { +namespace modelgen +{ -enum class OpCodes { +enum class OpCodes +{ opConv2d, opConcatenation, opDepthwiseConv2d, @@ -39,7 +41,8 @@ enum class OpCodes { opLast = opCount - 1, }; -namespace treebuilder { +namespace treebuilder +{ /** * opcode is a code of operation. @@ -51,7 +54,8 @@ namespace treebuilder { * not the kernel but specific data for operation. * */ -struct Operation { +struct Operation +{ OpCodes opcode; std::vector inputs; std::vector kernelShape; @@ -73,7 +77,8 @@ struct Operation { * for example: beginLevel[4] contains the id of first operation on the level 4. * id is index for opList array. */ -struct Tree { +struct Tree +{ int inputCnt; int hTree; std::vector inputShapeTree; @@ -83,7 +88,8 @@ struct Tree { std::vector> opList; }; -class TreeBuilder { +class TreeBuilder +{ public: TreeBuilder(); @@ -93,22 +99,23 @@ public: * inside every operation as size of input. This method are used when there aren't * operations on upper levels. */ - void initTree(Tree* t); - void buildLevel(Tree* t); + void initTree(Tree *t); + void buildLevel(Tree *t); - bool buildSketchOperation(Tree* t, Operation* op); + bool buildSketchOperation(Tree *t, Operation *op); /** * @details Currently Conv2D are build with stride = 1. * @param input_shape is the shape of input tensor. * @param op is the pointer to created operation. */ - void buildSketchConv2D(Tree* t, Operation* op); - void buildSketchConcat(Tree* t, Operation* op); - void buildSketchDepthwiseConv2D(Tree* t, Operation* op); - void buildSketchPooling(Tree* t, Operation* op); - void buildSketchSoftmax(Tree* t, Operation* op); - void buildSketchFullyConnected(Tree* t, Operation* op); + void buildSketchConv2D(Tree *t, Operation *op); + void buildSketchConcat(Tree *t, Operation *op); + void buildSketchDepthwiseConv2D(Tree *t, Operation *op); + void buildSketchPooling(Tree *t, Operation *op); + void buildSketchSoftmax(Tree *t, Operation *op); + void buildSketchFullyConnected(Tree *t, Operation *op); + private: /** * @lookupConsistentOutput It Looks up operation with conststent output's shape. @@ -123,11 +130,11 @@ private: * and return its id. * */ - int32_t lookupConsistentOutput(Tree* t, Operation* op, std::vector& shape, + int32_t lookupConsistentOutput(Tree *t, Operation *op, std::vector &shape, int32_t until_level); - void buildSketchConv2DForShape(std::vector& input_shape, Operation* op); - void addConcatInput(std::vector& input_shape, int32_t axis, Operation* op); + void buildSketchConv2DForShape(std::vector &input_shape, Operation *op); + void addConcatInput(std::vector &input_shape, int32_t axis, Operation *op); std::random_device _rd; std::mt19937 _gen; @@ -135,4 +142,4 @@ private: } // namespace treebuilder } // namespace modelgen -#endif //NNCC_TREE_H +#endif // NNCC_TREE_H -- 2.7.4