# Copyright (c) 2023 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.

load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")

#---------------------------------------------------------------------
# Config setting for Tensorflow build
config_setting(
    name = "build_with_acl",
    define_values = {
        "build_with_acl": "true",
    },
    visibility = ["//visibility:public"],
)

#---------------------------------------------------------------------
# Flags for build options. Example: --//:debug=true
# All flags have aliases in .bazelrc so can use for example --debug=true when building
bool_flag(
    name = "debug",
    build_setting_default = False,
    visibility = ["//visibility:public"],
)

bool_flag(
    name = "Werror",
    build_setting_default = False,
    visibility = ["//visibility:public"],
)

bool_flag(
    name = "logging",
    build_setting_default = False,
    visibility = ["//visibility:public"],
)

bool_flag(
    name = "openmp",
    build_setting_default = True,
    visibility = ["//visibility:public"],
)

bool_flag(
    name = "cppthreads",
    build_setting_default = False,
    visibility = ["//visibility:public"],
)

bool_flag(
    name = "enable_bf16_validation",
    build_setting_default = False,
    visibility = ["//visibility:public"],
)

bool_flag(
    name = "enable_sve_validation",
    build_setting_default = False,
    visibility = ["//visibility:public"],
)

string_flag(
    name = "arch",
    build_setting_default = "armv8-a",
    values = [
        "armv8-a",
        "armv8.2-a+fp16"
    ]
)

#---------------------------------------------------------------------
# Flag variables
config_setting(
    name = "debug_flag",
    flag_values = {
        ":debug": "true",
    },
)

config_setting(
    name = "Werror_flag",
    flag_values = {
        ":Werror": "true",
    },
)

config_setting(
    name = "logging_flag",
    flag_values = {
        ":logging": "true",
    },
)

config_setting(
    name = "openmp_flag",
    flag_values = {
        ":openmp": "true",
    },
)

config_setting(
    name = "cppthreads_flag",
    flag_values = {
        ":cppthreads": "true",
    },
)

config_setting(
    name = "bf16_validation_flag",
    flag_values = {
        ":enable_bf16_validation": "true",
    },
)

config_setting(
    name = "sve_validation_flag",
    flag_values = {
        ":enable_sve_validation": "true",
    },
)

config_setting(
    name = "arch_armv8-a",
    flag_values = {
        "arch": "armv8-a"
    }
)

config_setting(
    name = "arch_armv8.2-a+fp16",
    flag_values = {
        "arch": "armv8.2-a+fp16"
    }
)


#---------------------------------------------------------------------
# Common defines used for all targets
cc_library(
    name = "common_defines",
    defines = [
                  "ENABLE_NEON",
                  "ARM_COMPUTE_CPU_ENABLED",
                  "ARM_COMPUTE_ENABLE_NEON",
                  "ARM_COMPUTE_ENABLE_I8MM",
                  "ENABLE_FP32_KERNELS",
                  "ENABLE_QASYMM8_KERNELS",
                  "ENABLE_QASYMM8_SIGNED_KERNELS",
                  "ENABLE_QSYMM16_KERNELS",
                  "ENABLE_INTEGER_KERNELS",
                  "ENABLE_NHWC_KERNELS",
                  "ENABLE_NCHW_KERNELS",
                  "ARM_COMPUTE_GRAPH_ENABLED",
                  "ARM_COMPUTE_ENABLE_SVEF32MM",
                  "ARM_COMPUTE_ENABLE_FIXED_FORMAT_KERNELS",
                  "_GLIBCXX_USE_NANOSLEEP"
              ] + select({
                  "//:debug_flag": [
                      "ARM_COMPUTE_DEBUG_ENABLED",
                      "ARM_COMPUTE_ASSERTS_ENABLED",
                  ],
                  "//conditions:default": [],
              }) +
              select({
                  "//:logging_flag": ["ARM_COMPUTE_LOGGING_ENABLED"],
                  "//conditions:default": [],
              }) +
              select({
                  "//:cppthreads_flag": ["ARM_COMPUTE_CPP_SCHEDULER"],
                  "//conditions:default": [],
              }) +
              select({
                  "//:openmp_flag": ["ARM_COMPUTE_OPENMP_SCHEDULER"],
                  "//conditions:default": [],
              }) +
              select({
                  "//:arch_armv8-a": [],
                  "//:arch_armv8.2-a+fp16": ["ENABLE_FP16_KERNELS", "ARM_COMPUTE_ENABLE_FP16"],
                  "//conditions:default": [],
              }),
    visibility = ["//visibility:public"],
)

#---------------------------------------------------------------------
# Rule for creating file "arm_compute_version.embed"
genrule(
    name = "create_version_file",
    srcs = ["SConscript"],
    outs = ["arm_compute_version.embed"],
    cmd = "$(location //scripts:print_version_file) 'n/a' 'n/a' 'true' > $@",
    tools = ["//scripts:print_version_file"],
    visibility = ["//visibility:public"],
)

#---------------------------------------------------------------------
# Graph library

cc_library(
    name = "arm_compute_graph",
    srcs = ["//src:arm_compute_graph_srcs"],
    copts = [] + select({
                  "//:arch_armv8-a": ["-march=armv8-a"],
                  "//:arch_armv8.2-a+fp16": ["-march=armv8.2-a+fp16"],
                  "//conditions:default": ["-march=armv8-a"],
              }) + select({
                "//:debug_flag": [
                    "-O0",
                    "-g",
                    "-gdwarf-2",
                ],
                "//conditions:default": ["-O3"],
            }) +
            select({
                "//:openmp_flag": ["-fopenmp"],
                "//conditions:default": [],
            }) +
            select({
                "//:Werror_flag": ["-Werror"],
                "//conditions:default": [],
            }),
    visibility = ["//visibility:public"],
    deps = [
        "arm_compute",
        "//:common_defines",
        "//arm_compute:graph_headers",
    ],
    alwayslink = True,
)

#---------------------------------------------------------------------
# SVE2 library

cc_library(
    name = "arm_compute_sve2",
    srcs = ["//src:arm_compute_sve2_srcs"],
    copts = [
                "-march=armv8.6-a+sve2+fp16+dotprod",
            ] + select({
                "//:debug_flag": [
                    "-O0",
                    "-g",
                    "-gdwarf-2",
                ],
                "//conditions:default": ["-O3"],
            }) +
            select({
                "//:openmp_flag": ["-fopenmp"],
                "//conditions:default": [],
            }) +
            select({
                "//:Werror_flag": ["-Werror"],
                "//conditions:default": [],
            }),
    includes = [
        "src/core/NEON/kernels/arm_conv",
        "src/core/NEON/kernels/arm_gemm",
        "src/core/NEON/kernels/assembly",
        "src/core/cpu/kernels/assembly",
        "src/cpu/kernels/assembly",
    ],
    linkopts = select({
        "//:openmp_flag": ["-fopenmp"],
        "//conditions:default": [],
    }),
    local_defines = [
        "ENABLE_SVE",
        "ARM_COMPUTE_ENABLE_SVE",
        "ARM_COMPUTE_ENABLE_SVE2",
        "ARM_COMPUTE_ENABLE_BF16",
    ],
    deps = [
        "//:common_defines",
        "//arm_compute:core_headers",
        "//arm_compute:runtime_headers",
        "//include",
        "//support",
    ],
    alwayslink = True,
)

#---------------------------------------------------------------------
# SVE library

cc_library(
    name = "arm_compute_sve",
    srcs = ["//src:arm_compute_sve_srcs"],
    copts = [
                "-march=armv8.2-a+sve+fp16+dotprod",
            ] + select({
                "//:debug_flag": [
                    "-O0",
                    "-g",
                    "-gdwarf-2",
                ],
                "//conditions:default": ["-O3"],
            }) +
            select({
                "//:openmp_flag": ["-fopenmp"],
                "//conditions:default": [],
            }) +
            select({
                "//:Werror_flag": ["-Werror"],
                "//conditions:default": [],
            }),
    includes = [
        "src/core/NEON/kernels/arm_conv",
        "src/core/NEON/kernels/arm_gemm",
        "src/core/NEON/kernels/assembly",
        "src/core/cpu/kernels/assembly",
        "src/cpu/kernels/assembly",
    ],
    linkopts = select({
        "//:openmp_flag": ["-fopenmp"],
        "//conditions:default": [],
    }),
    local_defines = [
        "ENABLE_SVE",
        "ARM_COMPUTE_ENABLE_SVE",
        "ARM_COMPUTE_ENABLE_BF16",
    ],
    deps = [
        "//:common_defines",
        "//arm_compute:core_headers",
        "//arm_compute:runtime_headers",
        "//include",
        "//support",
    ],
    alwayslink = True,
)

#---------------------------------------------------------------------
# Core and Runtime library

cc_library(
    name = "arm_compute",
    srcs = ["//src:arm_compute_srcs"],
    hdrs = glob([
        "core/NEON/kernels/**/*.h",
        "core/NEON/kernels/**/*.hpp",
        "**/*.inl",
    ]) + [
        "//:create_version_file",
    ],
    copts = [] + select({
                  "//:arch_armv8-a": ["-march=armv8-a"],
                  "//:arch_armv8.2-a+fp16": ["-march=armv8.2-a+fp16"],
                  "//conditions:default": ["-march=armv8-a"],
              }) + select({
                "//:debug_flag": [
                    "-O0",
                    "-g",
                    "-gdwarf-2",
                ],
                "//conditions:default": ["-O3"],
            }) +
            select({
                "//:openmp_flag": ["-fopenmp"],
                "//conditions:default": [],
            }) +
            select({
                "//:Werror_flag": ["-Werror"],
                "//conditions:default": [],
            }),
    includes = [
        "arm_compute/runtime",
        "src/core/NEON/kernels/arm_gemm",
        "src/core/NEON/kernels/assembly",
        "src/core/NEON/kernels/convolution/common",
        "src/core/NEON/kernels/convolution/winograd",
        "src/core/cpu/kernels/assembly",
        "src/cpu/kernels/assembly",
    ],
    linkopts = select({
        "//:openmp_flag": ["-fopenmp"],
        "//conditions:default": [],
    }),
    local_defines = [
        "ENABLE_SVE",
        "ARM_COMPUTE_ENABLE_SVE",
        "ARM_COMPUTE_ENABLE_BF16",
    ],
    visibility = ["//visibility:public"],
    deps = [
        "//:common_defines",
        "//arm_compute:core_headers",
        "//arm_compute:graph_headers",
        "//arm_compute:runtime_headers",
        "//include",
        "//support",
        "//utils",
        "//:arm_compute_sve",
        "//:arm_compute_sve2"
    ],
    alwayslink = True,
)
