arm_compute v20.05
diff --git a/scripts/add_copyright.py b/scripts/add_copyright.py
new file mode 100755
index 0000000..9585fa3
--- /dev/null
+++ b/scripts/add_copyright.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python3
+import glob
+import os.path
+import sys
+
+mit_copyright = open("scripts/copyright_mit.txt",'r').read()
+
+def add_cpp_copyright( f, content):
+ global mit_copyright
+ out = open(f,'w')
+ out.write("/*\n")
+ for line in mit_copyright.split('\n')[:-1]:
+ out.write(" *");
+ if line.strip() != "":
+ out.write(" %s" %line)
+ out.write("\n")
+ out.write(" */\n")
+ out.write(content.strip())
+ out.write("\n")
+ out.close()
+
+def add_python_copyright( f, content):
+ global mit_copyright
+ out = open(f,'w')
+ for line in mit_copyright.split('\n')[:-1]:
+ out.write("#");
+ if line.strip() != "":
+ out.write(" %s" %line)
+ out.write("\n")
+ out.write(content.strip())
+ out.write("\n")
+ out.close()
+
+def remove_comment( content ):
+ comment=True
+ out=""
+ for line in content.split('\n'):
+ if comment:
+ if line.startswith(' */'):
+ comment=False
+ elif line.startswith('/*') or line.startswith(' *'):
+ #print(line)
+ continue
+ else:
+ raise Exception("ERROR: not a comment ? '%s'"% line)
+ else:
+ out += line + "\n"
+ return out
+def remove_comment_python( content ):
+ comment=True
+ out=""
+ for line in content.split('\n'):
+ if comment and line.startswith('#'):
+ continue
+ else:
+ comment = False
+ out += line + "\n"
+ return out
+
+def check_file( path ):
+ root, f = os.path.split(path)
+ if f in ['.clang-tidy', '.clang-format']:
+ print("Skipping file: {}".format(path))
+ return
+
+ with open(path, 'r', encoding='utf-8') as fd:
+ content = fd.read()
+ _, extension = os.path.splitext(f)
+
+ if extension in ['.cpp', '.h', '.hpp', '.inl', '.cl', '.in', '.cs']:
+ if not content.startswith('/*'):
+ add_cpp_copyright(path, content)
+ elif extension == '.py' or f in ['SConstruct', 'SConscript']:
+ if not content.startswith('# Copyright'):
+ add_python_copyright(path, content)
+ elif f == 'CMakeLists.txt':
+ if not content.startswith('# Copyright'):
+ add_python_copyright(path, content)
+ else:
+ raise Exception("Unhandled file: {}".format(path))
+
+if len(sys.argv) > 1:
+ for path in sys.argv[1:]:
+ check_file(path)
+else:
+ for top in ['./arm_compute', './tests','./src','./examples','./utils/','./opencl-1.2-stubs/','./opengles-3.1-stubs/','./support']:
+ for root, _, files in os.walk(top):
+ for f in files:
+ path = os.path.join(root, f)
+ check_file(path)
diff --git a/scripts/arm_compute_library_nn_driver.go b/scripts/arm_compute_library_nn_driver.go
index 320d5d8..553503f 100644
--- a/scripts/arm_compute_library_nn_driver.go
+++ b/scripts/arm_compute_library_nn_driver.go
@@ -17,6 +17,10 @@
cppflags = append(cppflags, "-fno-addrsig")
}
+ if ctx.AConfig().PlatformVersionName() == "R" || ctx.AConfig().PlatformVersionName() == "11" {
+ cppflags = append(cppflags, "-fno-addrsig")
+ }
+
return cppflags
}
diff --git a/scripts/caffe_mnist_image_extractor.py b/scripts/caffe_mnist_image_extractor.py
new file mode 100644
index 0000000..2c9478a
--- /dev/null
+++ b/scripts/caffe_mnist_image_extractor.py
@@ -0,0 +1,59 @@
+#!/usr/bin/env python
+"""Extracts mnist image data from the Caffe data files and stores them in numpy arrays
+Usage
+ python caffe_mnist_image_extractor.py -d path_to_caffe_data_directory -o desired_output_path
+
+Saves the first 10 images extracted as input10.npy, the first 100 images as input100.npy, and the
+corresponding labels to labels100.txt.
+
+Tested with Caffe 1.0 on Python 2.7
+"""
+import argparse
+import os
+import struct
+import numpy as np
+from array import array
+
+
+if __name__ == "__main__":
+ # Parse arguments
+ parser = argparse.ArgumentParser('Extract Caffe mnist image data')
+ parser.add_argument('-d', dest='dataDir', type=str, required=True, help='Path to Caffe data directory')
+ parser.add_argument('-o', dest='outDir', type=str, default='.', help='Output directory (default = current directory)')
+ args = parser.parse_args()
+
+ images_filename = os.path.join(args.dataDir, 'mnist/t10k-images-idx3-ubyte')
+ labels_filename = os.path.join(args.dataDir, 'mnist/t10k-labels-idx1-ubyte')
+
+ images_file = open(images_filename, 'rb')
+ labels_file = open(labels_filename, 'rb')
+ images_magic, images_size, rows, cols = struct.unpack('>IIII', images_file.read(16))
+ labels_magic, labels_size = struct.unpack('>II', labels_file.read(8))
+ images = array('B', images_file.read())
+ labels = array('b', labels_file.read())
+
+ input10_path = os.path.join(args.outDir, 'input10.npy')
+ input100_path = os.path.join(args.outDir, 'input100.npy')
+ labels100_path = os.path.join(args.outDir, 'labels100.npy')
+
+ outputs_10 = np.zeros(( 10, 28, 28, 1), dtype=np.float32)
+ outputs_100 = np.zeros((100, 28, 28, 1), dtype=np.float32)
+ labels_output = open(labels100_path, 'w')
+ for i in xrange(100):
+ image = np.array(images[i * rows * cols : (i + 1) * rows * cols]).reshape((rows, cols)) / 256.0
+ outputs_100[i, :, :, 0] = image
+
+ if i < 10:
+ outputs_10[i, :, :, 0] = image
+
+ if i == 10:
+ np.save(input10_path, np.transpose(outputs_10, (0, 3, 1, 2)))
+ print "Wrote", input10_path
+
+ labels_output.write(str(labels[i]) + '\n')
+
+ labels_output.close()
+ print "Wrote", labels100_path
+
+ np.save(input100_path, np.transpose(outputs_100, (0, 3, 1, 2)))
+ print "Wrote", input100_path
diff --git a/scripts/check_bad_style.sh b/scripts/check_bad_style.sh
new file mode 100755
index 0000000..acc496b
--- /dev/null
+++ b/scripts/check_bad_style.sh
@@ -0,0 +1,105 @@
+#!/bin/bash
+
+set -e
+
+ALL_DIRECTORIES="./arm_compute ./src ./examples ./tests ./utils ./support"
+
+#If no arguments were passed: default to check all the folders:
+if [ ! -n "$1" ]
+then
+ FILES=$ALL_DIRECTORIES
+else
+ #else only check the files that were passed on the command line:
+ FILES=$@
+fi
+
+grep -HrnP --exclude-dir=assembly --exclude-dir=convolution --exclude-dir=arm_gemm "/\*\*$" $FILES | tee bad_style.log
+if (( `cat bad_style.log | wc -l` > 0 ))
+then
+ echo ""
+ echo "ERROR: Doxygen comments should start on the first line: \"/** My comment\""
+ exit -1
+fi
+
+grep -Hnr --exclude-dir=assembly --exclude-dir=convolution --exclude-dir=arm_gemm --exclude=Doxyfile "@brief" $FILES | tee bad_style.log
+if (( `cat bad_style.log | wc -l` > 0 ))
+then
+ echo ""
+ echo "ERROR: Doxygen comments shouldn't use '@brief'"
+ exit -1
+fi
+
+grep -HnRE --exclude-dir=assembly --exclude-dir=convolution --exclude-dir=arm_gemm "\buint " --exclude-dir=cl_kernels --exclude-dir=cs_shaders $FILES | tee bad_style.log
+if [[ $(cat bad_style.log | wc -l) > 0 ]]
+then
+ echo ""
+ echo "ERROR: C/C++ don't define 'uint'. Use 'unsigned int' instead."
+ exit -1
+fi
+
+grep -HnR --exclude-dir=assembly --exclude-dir=convolution --exclude-dir=arm_gemm "float32_t" $FILES | tee bad_style.log
+if [[ $(cat bad_style.log | wc -l) > 0 ]]
+then
+ echo ""
+ echo "ERROR: C/C++ don't define 'float32_t'. Use 'float' instead."
+ exit -1
+fi
+
+grep -Hnir --exclude-dir=assembly --exclude-dir=convolution --exclude-dir=arm_gemm "arm[_ ]\?cv" $FILES | tee bad_style.log
+if [[ $(cat bad_style.log | wc -l) > 0 ]]
+then
+ echo ""
+ echo "ERROR: Reference to arm_cv detected in the files above (Replace with arm_compute)"
+ exit -1
+fi
+
+grep -Hnir --exclude-dir=assembly --exclude-dir=convolution --exclude-dir=arm_gemm "#.*if.*defined[^(]" $FILES | tee bad_style.log
+if [[ $(cat bad_style.log | wc -l) > 0 ]]
+then
+ echo ""
+ echo "ERROR: use parenthesis after #if defined(MY_PREPROCESSOR)"
+ exit -1
+fi
+
+grep -Hnir --exclude-dir=assembly --exclude-dir=convolution --exclude-dir=arm_gemm "#else$\|#endif$" $FILES | tee bad_style.log
+if [[ $(cat bad_style.log | wc -l) > 0 ]]
+then
+ echo ""
+ echo "ERROR: #else and #endif should be followed by a comment of the guard they refer to (e.g /* ARM_COMPUTE_AARCH64_V8_2 */ )"
+ exit -1
+fi
+
+grep -Hnir --exclude-dir=assembly --exclude-dir=convolution --exclude-dir=arm_gemm "ARM_COMPUTE_AARCH64_V8_2" ./tests/validation/CL | tee bad_style.log
+if [[ $(cat bad_style.log | wc -l) > 0 ]]
+then
+ echo ""
+ echo "ERROR: Found ARM_COMPUTE_AARCH64_V8_2 in CL tests though armv8.2 features (FP16) are always supported for OpenCL"
+ exit -1
+fi
+
+spdx_missing=0
+for f in $(find $FILES -type f)
+do
+ if [[ $(grep SPDX $f | wc -l) == 0 ]]
+ then
+ # List of exceptions:
+ case `basename $f` in
+ "arm_compute_version.embed");;
+ ".clang-format");;
+ ".clang-tidy");;
+ "README.md");;
+ #It's an error for other files to not contain the MIT header:
+ *)
+ spdx_missing=1
+ echo $f;
+ ;;
+ esac
+ fi;
+done
+
+if [[ $spdx_missing > 0 ]]
+then
+ echo ""
+ echo "ERROR: MIT Copyright header missing from the file(s) above."
+ exit -1
+fi
diff --git a/scripts/clang-tidy.h b/scripts/clang-tidy.h
new file mode 100644
index 0000000..b370512
--- /dev/null
+++ b/scripts/clang-tidy.h
@@ -0,0 +1,177 @@
+#include <arm_neon.h>
+
+inline float16x4_t vrsqrts_f16 (float16x4_t, float16x4_t)
+{
+ return vdup_n_f16(0);
+}
+
+inline float16x8_t vrsqrtsq_f16 (float16x8_t, float16x8_t)
+{
+ return vdupq_n_f16(0);
+}
+
+inline float16x4_t vpmax_f16 (float16x4_t, float16x4_t)
+{
+ return vdup_n_f16(0);
+}
+
+inline float16x4_t vpadd_f16(float16x4_t, float16x4_t)
+{
+ return vdup_n_f16(0);
+}
+
+inline float16x8_t vmulq_lane_f16 (float16x8_t, float16x4_t, const int)
+{
+ return vdupq_n_f16(0);
+}
+
+inline float16x4_t vmul_f16 (float16x4_t, float16x4_t)
+{
+ return vdup_n_f16(0);
+}
+
+inline float16x4_t vadd_f16 (float16x4_t, float16x4_t)
+{
+ return vdup_n_f16(0);
+}
+
+inline float16x4_t vmul_lane_f16 (float16x4_t, float16x4_t, const int)
+{
+ return vdup_n_f16(0);
+}
+
+inline float16x4_t vmul_n_f16 (float16x4_t, float16_t)
+{
+ return vdup_n_f16(0);
+}
+
+inline float16x4_t vmax_f16(float16x4_t, float16x4_t)
+{
+ return vdup_n_f16(0);
+}
+
+inline float16x8_t vcvtq_f16_u16(uint16x8_t)
+{
+ return vdupq_n_f16(0);
+}
+
+inline uint16x8_t vcvtq_u16_f16(float16x8_t)
+{
+ return vdupq_n_u16(0);
+}
+
+inline int16x8_t vcvtq_s16_f16(float16x8_t)
+{
+ return vdupq_n_s16(0);
+}
+
+inline float16x8_t vaddq_f16(float16x8_t, float16x8_t)
+{
+ return vdupq_n_f16(0);
+}
+
+inline float16x8_t vsubq_f16(float16x8_t, float16x8_t)
+{
+ return vdupq_n_f16(0);
+}
+
+inline float16x8_t vmulq_f16(float16x8_t, float16x8_t)
+{
+ return vdupq_n_f16(0);
+}
+
+inline float16x8_t vmulq_n_f16(float16x8_t, float16_t)
+{
+ return vdupq_n_f16(0);
+}
+
+inline float16x8_t vfmaq_f16(float16x8_t, float16x8_t, float16x8_t)
+{
+ return vdupq_n_f16(0);
+}
+
+inline uint16x8_t vcgeq_f16(float16x8_t, float16x8_t)
+{
+ return vdupq_n_u16(0);
+}
+
+inline uint16x8_t vcgtq_f16(float16x8_t, float16x8_t)
+{
+ return vdupq_n_u16(0);
+}
+
+inline float16x8_t vbslq_f16 (uint16x8_t, float16x8_t, float16x8_t)
+{
+ return vdupq_n_f16(0);;
+}
+
+inline float16x8_t vextq_f16(float16x8_t, float16x8_t, int)
+{
+ return vdupq_n_f16(0);
+}
+
+inline float16x8_t vabsq_f16(float16x8_t)
+{
+ return vdupq_n_f16(0);
+}
+
+inline uint16x8_t vcvtq_f16_s16(float16x8_t)
+{
+ return vdupq_n_s16(0);
+}
+
+inline float16x4_t vbsl_f16 (uint16x4_t,float16x4_t, float16x4_t)
+{
+ return vdup_n_f16(0);
+}
+
+inline float16x4_t vrsqrte_f16(float16x4_t)
+{
+ return vdup_n_f16(0);
+}
+
+inline float16x8_t vrsqrteq_f16(float16x8_t)
+{
+ return vdupq_n_f16(0);
+}
+
+inline float16x8_t vfmsq_f16 (float16x8_t, float16x8_t, float16x8_t)
+{
+ return vdupq_n_f16(0);
+}
+
+inline float16x4_t vrecpe_f16 (float16x4_t)
+{
+ return vdup_n_f16(0);
+}
+
+inline float16x8_t vrecpeq_f16 (float16x8_t)
+{
+ return vdupq_n_f16(0);
+}
+
+inline float16x4_t vrecps_f16 (float16x4_t, float16x4_t)
+{
+ return vdup_n_f16(0);
+}
+
+inline float16x8_t vrecpsq_f16 (float16x8_t, float16x8_t)
+{
+ return vdupq_n_f16(0);
+}
+
+inline float16x8_t vmaxq_f16 (float16x8_t, float16x8_t)
+{
+ return vdupq_n_f16(0);
+}
+
+inline float16x8_t vminq_f16 (float16x8_t, float16x8_t)
+{
+ return vdupq_n_f16(0);
+}
+
+inline uint16x8_t vcltq_f16(float16x8_t, float16x8_t)
+{
+ return vdupq_n_u16(0);
+}
+
diff --git a/scripts/clang_tidy_rules.py b/scripts/clang_tidy_rules.py
new file mode 100755
index 0000000..a030f21
--- /dev/null
+++ b/scripts/clang_tidy_rules.py
@@ -0,0 +1,166 @@
+#!/usr/bin/env python3
+import os
+import re
+import sys
+
+def get_list_includes():
+ return "arm_compute/core/NEON/kernels/assembly " \
+ "arm_compute/core/NEON/kernels/convolution/common " \
+ "arm_compute/core/NEON/kernels/convolution/depthwise " \
+ "arm_compute/core/NEON/kernels/convolution/winograd " \
+ "include/linux include " \
+ ". " \
+ "3rdparty/include kernels".split()
+
+def get_list_flags( filename, arch):
+ assert arch in ["armv7", "aarch64"]
+ flags = ["-std=c++11"]
+ flags.append("-DARM_COMPUTE_CPP_SCHEDULER=1")
+ flags.append("-DARM_COMPUTE_CL")
+ flags.append("-DARM_COMPUTE_GC")
+ if arch == "aarch64":
+ flags.append("-DARM_COMPUTE_AARCH64_V8_2")
+ return flags
+
+def filter_files( list_files ):
+ to_check = []
+ for f in list_files:
+ if os.path.splitext(f)[1] != ".cpp":
+ continue
+ # Skip OMPScheduler as it causes problems in clang
+ if (("OMPScheduler.cpp" in f) or
+ ("CLTracePoint.cpp" in f) or
+ ("NETracePoint.cpp" in f) or
+ ("TracePoint.cpp" in f)):
+ continue
+ to_check.append(f)
+ return to_check
+
+def filter_clang_tidy_lines( lines ):
+ out = []
+ print_context=False
+ for i in range(0, len(lines)):
+ line = lines[i]
+
+ if "/arm_gemm/" in line:
+ continue
+
+ if "/convolution/" in line:
+ continue
+
+ if "/validate_examples/" in line:
+ continue
+
+ if "error:" in line:
+ if (("Version.cpp" in line and "arm_compute_version.embed" in line and "file not found" in line) or
+ ("arm_fp16.h" in line) or
+ ("omp.h" in line) or
+ ("cast from pointer to smaller type 'uintptr_t' (aka 'unsigned int') loses information" in line) or
+ ("cast from pointer to smaller type 'cl_context_properties' (aka 'int') loses information" in line) or
+ ("cast from pointer to smaller type 'std::uintptr_t' (aka 'unsigned int') loses information" in line) or
+ ("NEMath.inl" in line and "statement expression not allowed at file scope" in line) or
+ ("Utils.h" in line and "no member named 'unmap' in 'arm_compute::Tensor'" in line) or
+ ("Utils.h" in line and "no member named 'map' in 'arm_compute::Tensor'" in line) or
+ ("CPUUtils.cpp" in line and "'asm/hwcap.h' file not found" in line) or
+ "3rdparty" in line or
+ ("'arm_compute_version.embed' file not found" in line) ):
+ print_context=False
+ continue
+
+ out.append(line)
+ print_context=True
+ elif "warning:" in line:
+ if ("uninitialized record type: '__ret'" in line or
+ "local variable '__bound_functor' is still referred to by the global variable '__once_callable'" in line or
+ "assigning newly created 'gsl::owner<>'" in line or
+ "calling legacy resource function without passing a 'gsl::owner<>'" in line or
+ "deleting a pointer through a type that is not marked 'gsl::owner<>'" in line or
+ (any(f in line for f in ["Error.cpp","Error.h"]) and "thrown exception type is not nothrow copy constructible" in line) or
+ (any(f in line for f in ["Error.cpp","Error.h"]) and "uninitialized record type: 'args'" in line) or
+ (any(f in line for f in ["Error.cpp","Error.h"]) and "do not call c-style vararg functions" in line) or
+ (any(f in line for f in ["Error.cpp","Error.h"]) and "do not define a C-style variadic function" in line) or
+ ("TensorAllocator.cpp" in line and "warning: pointer parameter 'ptr' can be pointer to const" in line) or
+ ("TensorAllocator.cpp" in line and "warning: do not declare C-style arrays" in line) or
+ ("RawTensor.cpp" in line and "warning: pointer parameter 'ptr' can be pointer to const" in line) or
+ ("RawTensor.cpp" in line and "warning: do not declare C-style arrays" in line) or
+ ("GCBufferAllocator.cpp" in line and "warning: initializing non-owner" in line) or
+ ("NEMinMaxLocationKernel.cpp" in line and "move constructors should be marked noexcept" in line) or
+ ("NEMinMaxLocationKernel.cpp" in line and "move assignment operators should be marked noexcept" in line) or
+ ("CLMinMaxLocationKernel.cpp" in line and "Forming reference to null pointer" in line) or
+ ("PMUCounter.cpp" in line and "consider replacing 'long long' with 'int64'" in line) or
+ ("Validation.cpp" in line and "parameter 'classified_labels' is unused" in line) or
+ ("Validation.cpp" in line and "parameter 'expected_labels' is unused" in line) or
+ ("Reference.cpp" in line and "parameter 'rois' is unused" in line) or
+ ("Reference.cpp" in line and "parameter 'shapes' is unused" in line) or
+ ("Reference.cpp" in line and re.search(r"parameter '[^']+' is unused", line)) or
+ ("ReferenceCPP.cpp" in line and "parameter 'rois' is unused" in line) or
+ ("ReferenceCPP.cpp" in line and "parameter 'srcs' is unused" in line) or
+ ("ReferenceCPP.cpp" in line and re.search(r"parameter '[^']+' is unused", line)) or
+ ("NEGEMMMatrixMultiplyKernel.cpp" in line and "do not use C-style cast to convert between unrelated types" in line) or
+ ("NEPoolingLayerKernel.cpp" in line and "do not use C-style cast to convert between unrelated types" in line) or
+ ("NESoftmaxLayerKernel.cpp" in line and "macro argument should be enclosed in parentheses" in line) or
+ ("GraphUtils.cpp" in line and "consider replacing 'unsigned long' with 'uint32'" in line) or
+ ("GraphUtils.cpp" in line and "consider replacing 'unsigned long' with 'uint64'" in line) or
+ ("ConvolutionLayer.cpp" in line and "move assignment operators should be marked noexcept" in line) or
+ ("ConvolutionLayer.cpp" in line and "move constructors should be marked noexcept" in line) or
+ ("parameter 'memory_manager' is unused" in line) or
+ ("parameter 'memory_manager' is copied for each invocation but only used as a const reference" in line) or
+ ("DeconvolutionLayer.cpp" in line and "casting (double + 0.5) to integer leads to incorrect rounding; consider using lround" in line) or
+ ("NEWinogradLayerKernel.cpp" in line and "use '= default' to define a trivial destructor" in line) or
+ ("NEGEMMLowpMatrixMultiplyCore.cpp" in line and "constructor does not initialize these fields" in line) or
+ ("NEGEMMLowpAssemblyMatrixMultiplyCore" in line and "constructor does not initialize these fields" in line) or
+ ("CPUUtils.cpp" in line and "consider replacing 'unsigned long' with 'uint64'" in line) or
+ ("CPUUtils.cpp" in line and "parameter 'cpusv' is unused" in line) or
+ ("CPUUtils.cpp" in line and "warning: uninitialized record type" in line) or
+ ("GCKernelLibrary.cpp" in line and "warning: do not declare C-style arrays" in line) or
+ ("Utils.h" in line and "warning: Use of zero-allocated memory" in line) or
+ "3rdparty" in line):
+ print_context=False
+ continue
+
+ if "do not use C-style cast to convert between unrelated types" in line:
+ if i + 1 < len(lines) and "vgetq_lane_f16" in lines[i + 1]:
+ print_context=False
+ continue
+
+ if "use 'using' instead of 'typedef'" in line:
+ if i + 1 < len(lines) and "BOOST_FIXTURE_TEST_SUITE" in lines[i + 1]:
+ print_context=False
+ continue
+
+ if "do not call c-style vararg functions" in line:
+ if (i + 1 < len(lines) and
+ ("BOOST_TEST" in lines[i + 1] or
+ "BOOST_FAIL" in lines[i + 1] or
+ "BOOST_CHECK_THROW" in lines[i + 1] or
+ "ARM_COMPUTE_ERROR_VAR" in lines[i + 1] or
+ "ARM_COMPUTE_RETURN_ON" in lines[i + 1] or
+ "syscall" in lines[i + 1])):
+ print_context=False
+ continue
+
+ out.append(line)
+ print_context=True
+ elif (("CLMinMaxLocationKernel.cpp" in line and "'?' condition is false" in line) or
+ ("CLMinMaxLocationKernel.cpp" in line and "Assuming the condition is false" in line) or
+ ("CLMinMaxLocationKernel.cpp" in line and "Assuming pointer value is null" in line) or
+ ("CLMinMaxLocationKernel.cpp" in line and "Forming reference to null pointer" in line)):
+ print_context=False
+ continue
+ elif print_context:
+ out.append(line)
+
+ return out
+
+if __name__ == "__main__":
+ if len(sys.argv) != 2:
+ print("usage: {} CLANG-TIDY_OUTPUT_FILE".format(sys.argv[0]))
+ sys.exit(1)
+
+ errors = []
+ with open(sys.argv[1], mode="r") as clang_tidy_file:
+ lines = clang_tidy_file.readlines()
+ errors = filter_clang_tidy_lines(lines)
+ print("\n".join(errors))
+
+ sys.exit(0 if len(errors) == 0 else 1)
diff --git a/scripts/copyright_eula.txt b/scripts/copyright_eula.txt
new file mode 100644
index 0000000..50e8090
--- /dev/null
+++ b/scripts/copyright_eula.txt
@@ -0,0 +1,19 @@
+Copyright (c) 2016, 2017 ARM Limited.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/scripts/copyright_mit.txt b/scripts/copyright_mit.txt
new file mode 100644
index 0000000..a43ef66
--- /dev/null
+++ b/scripts/copyright_mit.txt
@@ -0,0 +1,21 @@
+Copyright (c) 2018 ARM Limited.
+
+SPDX-License-Identifier: MIT
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/scripts/enable_tracing.py b/scripts/enable_tracing.py
new file mode 100755
index 0000000..3379e53
--- /dev/null
+++ b/scripts/enable_tracing.py
@@ -0,0 +1,137 @@
+#
+# Copyright (c) 2020 ARM Limited.
+#
+# SPDX-License-Identifier: MIT
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+#
+#!/usr/bin/env python
+import re
+import os
+import sys
+import argparse
+import fnmatch
+import logging
+
+import json
+import glob
+
+logger = logging.getLogger("acl_tracing")
+
+# Returns the files matching the given pattern
+def find(path, pattern):
+ matches = []
+ for root, dirnames, filenames, in os.walk(path):
+ for filename in fnmatch.filter(filenames, pattern):
+ matches.append(os.path.join(root,filename))
+ return matches
+
+# Returns the class name (Core or Runtime) and arguments of the given function
+def get_class_and_args(function):
+ decl = " ".join(function_signature)
+ m = re.match("void ([^:]+)::configure\(([^)]*)\)", decl)
+ if m:
+ assert m, "Can't parse '%s'" % line
+ class_name = m.group(1)
+ args = m.group(2)
+ #Remove comments:
+ args = re.sub("\/\*.*?\*\/","",args)
+ #Remove templates
+ args = re.sub("<.*?>","",args)
+ logger.debug(args)
+ arg_names = []
+ for arg in args.split(","):
+ m = re.match(".*?([^ &*]+)$", arg.strip())
+ arg_names.append(m.group(1))
+ logger.debug(" %s" % m.group(1))
+ return (class_name, arg_names)
+ else:
+ return ('','')
+
+# Adds the tracepoints to the source file for the given function
+def do_insert_tracing(source, function, fd):
+ logger.debug("Full signature = %s" % " ".join(function_signature))
+ class_name, arg_names = get_class_and_args(function)
+ if len(arg_names):
+ assert len(arg_names), "No argument to configure for %s ?" % class_name
+ spaces = re.match("([ ]*)void", function[0]).group(1)
+ fd.write("%s CREATE_TRACEPOINT(%s, \"%s\", this, TracePoint::Args()" % (spaces, source, class_name))
+ for arg in arg_names:
+ fd.write("<<%s" % arg)
+ fd.write(");\n")
+ else:
+ print('Failed to get class name in %s ' % " ".join(function_signature))
+
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser(
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ description="Post process JSON benchmark files",
+ )
+
+ parser.add_argument("-D", "--debug", action='store_true', help="Enable script debugging output")
+ args = parser.parse_args()
+ logging_level = logging.INFO
+ if args.debug:
+ logging_level = logging.DEBUG
+ logging.basicConfig(level=logging_level)
+ logger.debug("Arguments passed: %s" % str(args.__dict__))
+ for f in find("src","*.cpp"):
+ logger.debug(f)
+ fd = open(f,'r+')
+ lines = fd.readlines()
+ contains_configure = False
+ for line in lines:
+ if re.search(r"void.*::configure\(",line):
+ contains_configure = True
+ break
+ if not contains_configure:
+ continue
+ fd.seek(0)
+ fd.truncate()
+ function_signature = None
+ insert_tracing = False
+ start = True
+ for line in lines:
+ write = True
+ if start:
+ if not (line.startswith("/*") or line.startswith(" *") or line.startswith("#") or len(line.strip()) == 0):
+ start = False
+ fd.write("#include \"arm_compute/core/TracePoint.h\"\n")
+ elif not function_signature:
+ if re.search(r"void.*::configure\(",line):
+ function_signature = [ line.rstrip() ]
+ else:
+ if re.search("[ ]*{$", line):
+ insert_tracing = True
+ else:
+ function_signature.append(line.rstrip())
+ if write:
+ fd.write(line)
+ if insert_tracing:
+ if "/core/" in f:
+ source = "TracePoint::Layer::CORE"
+ elif "/runtime/" in f:
+ source = "TracePoint::Layer::RUNTIME"
+ else:
+ assert "Can't find layer for file %s" %f
+ do_insert_tracing(source, function_signature, fd)
+ insert_tracing = False
+ function_signature = None
diff --git a/scripts/format_doxygen.py b/scripts/format_doxygen.py
new file mode 100755
index 0000000..5882958
--- /dev/null
+++ b/scripts/format_doxygen.py
@@ -0,0 +1,166 @@
+#!/usr/bin/env python3
+import os.path
+import re
+import sys
+
+def process_comment(fd, comment, first_param, last_param):
+ if first_param < 0:
+ # Nothing to do: just copy the comment
+ fd.write("".join(comment))
+ else:
+ params = list()
+
+ # Measure the indentation of the first param and use that to create an empty comment line string:
+ m = re.match(r" */", comment[0])
+
+ if not m:
+ raise Exception("{}: Not a comment ? '{}'".format(path,comment[first_param]))
+
+ line_prefix = " " * len(m.group(0)) + "*"
+ empty_line = line_prefix +"\n"
+
+ fd.write(comment[0])
+ # Copy the non param lines with the correct indentation:
+ for comment_line in range(1,first_param):
+ line = comment[comment_line]
+ m = re.match(" *\*(.*)", line)
+ if not m:
+ raise Exception("{}:{}: Not a comment line ? ".format(path, n_line - len(comment) + comment_line + 1))
+ fd.write(line_prefix+ m.group(1)+"\n")
+
+ # For each param split the line into 3 columns: param, param_name, description
+ for param in range(first_param, last_param):
+ m = re.match(r"[^@]+(@param\[[^\]]+\]) +(\S+) +(.+)", comment[param])
+
+ if m:
+ params.append( (" "+m.group(1), m.group(2), m.group(3)) )
+ else:
+ # If it's not a match then it must be a multi-line param description:
+
+ m = re.match(" *\* +(.*)", comment[param])
+ if not m:
+ raise Exception("{}:{}: Not a comment line ? ".format(path, n_line - len(comment) + param + 1))
+
+ params.append( ("", "", m.group(1)) )
+
+ # Now that we've got a list of params, find what is the longest string for each column:
+ max_len = [0, 0]
+
+ for p in params:
+ for l in range(len(max_len)):
+ max_len[l] = max(max_len[l], len(p[l]))
+
+ # Insert an empty line if needed before the first param to make it easier to read:
+ m = re.match(r" *\* *$", comment[first_param - 1])
+
+ if not m:
+ # insert empty line
+ fd.write(empty_line)
+
+ # Write out the formatted list of params:
+ for p in params:
+ fd.write("{}{}{} {}{} {}\n".format( line_prefix,
+ p[0], " " * (max_len[0] - len(p[0])),
+ p[1], " " * (max_len[1] - len(p[1])),
+ p[2]))
+
+ # If the next line after the list of params is a command (@return, @note, @warning, etc), insert an empty line to separate it from the list of params
+ if last_param < len(comment) - 1:
+ if re.match(r" *\* *@\w+", comment[last_param]):
+ # insert empty line
+ fd.write(empty_line)
+
+ # Copy the remaining of the comment with the correct indentation:
+ for comment_line in range(last_param,len(comment)):
+ line = comment[comment_line]
+ m = re.match(" *\*(.*)", line)
+ if not m:
+ raise Exception("{}:{}: Not a comment line ? ".format(path, n_line - len(comment) + comment_line + 1))
+ fd.write(line_prefix+ m.group(1)+"\n")
+
+if __name__ == "__main__":
+ n_file=0
+
+ if len(sys.argv) == 1:
+ paths = []
+
+ for top_level in ["./arm_compute", "./src", "./examples", "./tests", "./utils", "./framework", "./support"]:
+ for root, _, files in os.walk(top_level):
+ paths.extend([os.path.join(root, f) for f in files])
+ else:
+ paths = sys.argv[1:]
+
+ for path in paths:
+ if (path[-3:] not in ("cpp", "inl") and
+ path[-2:] not in ("cl") and
+ path[-2:] not in ("cs") and
+ path[-1] not in ("h")):
+ continue
+
+ print("[{}] {}".format(n_file, path))
+
+ n_file += 1
+
+ with open(path,'r+', encoding="utf-8") as fd:
+ comment = list()
+ first_param = -1
+ last_param = -1
+ n_line = 0
+
+ lines = fd.readlines()
+ fd.seek(0)
+ fd.truncate()
+
+ for line in lines:
+ n_line += 1
+
+ # Start comment
+ # Match C-style comment /* anywhere in the line
+ if re.search(r"/\*", line):
+ #print("Start comment {}".format(n_line))
+
+ if len(comment) > 0:
+ raise Exception("{}:{}: Already in a comment!".format(path,n_line))
+
+ comment.append(line)
+
+ # Comment already started
+ elif len(comment) > 0:
+ #print("Add line to comment {}".format(n_line))
+
+ comment.append(line)
+
+ # Non-comment line
+ else:
+ #print("Normal line {}".format(n_line))
+
+ fd.write(line)
+
+ # Match param declaration in Doxygen comment
+ # @param[in] name description
+ if re.search(r"@param\[[^\]]+\] +\S+ +\S", line):
+ #print("Param {}".format(n_line))
+
+ if first_param < 0:
+ first_param = len(comment) - 1
+
+ last_param = len(comment)
+
+ # Match end of C-style comment */
+ if re.search(r"\*/", line):
+ if re.search('"[^"]*\*/[^"]*"', line):
+ #print("End of comment inside a string: ignoring")
+ pass
+ else:
+ #print("End comment {}".format(n_line))
+
+ if len(comment) < 1:
+ raise Exception("{}:{}: Was not in a comment! ".format(path, n_line))
+
+ #print("Process comment {} {}".format(first_param, last_param))
+
+ process_comment(fd, comment, first_param, last_param)
+
+ comment = list()
+ first_param = -1
+ last_param = -1
diff --git a/scripts/include_functions_kernels.py b/scripts/include_functions_kernels.py
new file mode 100755
index 0000000..074f794
--- /dev/null
+++ b/scripts/include_functions_kernels.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+import glob
+import collections
+import os
+
+Target = collections.namedtuple('Target', 'name prefix')
+
+targets = [Target("NEON", "NE"), Target("CL", "CL"), Target("CPP", "CPP"), Target("GLES_COMPUTE", "GC")]
+
+armcv_path = "arm_compute"
+core_path = armcv_path + "/core/"
+runtime_path = armcv_path + "/runtime/"
+include_str = "#include \""
+
+
+def read_file(file):
+ with open(file, "r") as f:
+ lines = f.readlines()
+ return lines
+
+
+def write_file(file, lines):
+ with open(file, "w") as f:
+ for line in lines:
+ f.write(line)
+
+
+def remove_existing_includes(lines):
+ first_pos = next(i for i, line in enumerate(lines) if include_str in line)
+ return [x for x in lines if not x.startswith(include_str)], first_pos
+
+
+def add_updated_includes(lines, pos, includes):
+ lines[pos:pos] = includes
+ return lines
+
+
+def create_include_list(folder):
+ files_path = folder + "/*.h"
+ files = glob.glob(files_path)
+ updated_files = [include_str + folder + "/" + x.rsplit('/',1)[1] + "\"\n" for x in files]
+ updated_files.sort()
+ return updated_files
+
+
+def include_components(path, header_prefix, folder, subfolders=None):
+ for t in targets:
+ target_path = path + t.name + "/"
+ components_file = target_path + t.prefix + header_prefix
+ if os.path.exists(components_file):
+ include_list = create_include_list(target_path + folder)
+ for s in subfolders or []:
+ include_list += create_include_list( target_path + folder + "/" + s)
+ include_list.sort()
+ lines = read_file(components_file)
+ lines, first_pos = remove_existing_includes(lines)
+ lines = add_updated_includes(lines, first_pos, include_list)
+ write_file(components_file, lines)
+
+
+if __name__ == "__main__":
+ # Include kernels
+ include_components(core_path, "Kernels.h", "kernels", ["arm32", "arm64"])
+
+ # Include functions
+ include_components(runtime_path, "Functions.h", "functions")
diff --git a/scripts/tf_frozen_model_extractor.py b/scripts/tf_frozen_model_extractor.py
new file mode 100644
index 0000000..fbd5b38
--- /dev/null
+++ b/scripts/tf_frozen_model_extractor.py
@@ -0,0 +1,62 @@
+#!/usr/bin/env python
+""" Extract trainable parameters from a frozen model and stores them in numpy arrays.
+Usage:
+ python tf_frozen_model_extractor -m path_to_frozem_model -d path_to_store_the_parameters
+
+Saves each variable to a {variable_name}.npy binary file.
+
+Note that the script permutes the trainable parameters to NCHW format. This is a pretty manual step thus it's not thoroughly tested.
+"""
+import argparse
+import os
+import numpy as np
+import tensorflow as tf
+from tensorflow.python.platform import gfile
+
+strings_to_remove=["read", "/:0"]
+permutations = { 1 : [0], 2 : [1, 0], 3 : [2, 1, 0], 4 : [3, 2, 0, 1]}
+
+if __name__ == "__main__":
+ # Parse arguments
+ parser = argparse.ArgumentParser('Extract TensorFlow net parameters')
+ parser.add_argument('-m', dest='modelFile', type=str, required=True, help='Path to TensorFlow frozen graph file (.pb)')
+ parser.add_argument('-d', dest='dumpPath', type=str, required=False, default='./', help='Path to store the resulting files.')
+ parser.add_argument('--nostore', dest='storeRes', action='store_false', help='Specify if files should not be stored. Used for debugging.')
+ parser.set_defaults(storeRes=True)
+ args = parser.parse_args()
+
+ # Create directory if not present
+ if not os.path.exists(args.dumpPath):
+ os.makedirs(args.dumpPath)
+
+ # Extract parameters
+ with tf.Graph().as_default() as graph:
+ with tf.Session() as sess:
+ print("Loading model.")
+ with gfile.FastGFile(args.modelFile, 'rb') as f:
+ graph_def = tf.GraphDef()
+ graph_def.ParseFromString(f.read())
+ sess.graph.as_default()
+
+ tf.import_graph_def(graph_def, input_map=None, return_elements=None, name="", op_dict=None, producer_op_list=None)
+
+ for op in graph.get_operations():
+ for op_val in op.values():
+ varname = op_val.name
+
+ # Skip non-const values
+ if "read" in varname:
+ t = op_val.eval()
+ tT = t.transpose(permutations[len(t.shape)])
+ t = np.ascontiguousarray(tT)
+
+ for s in strings_to_remove:
+ varname = varname.replace(s, "")
+ if os.path.sep in varname:
+ varname = varname.replace(os.path.sep, '_')
+ print("Renaming variable {0} to {1}".format(op_val.name, varname))
+
+ # Store files
+ if args.storeRes:
+ print("Saving variable {0} with shape {1} ...".format(varname, t.shape))
+ np.save(os.path.join(args.dumpPath, varname), t)