Add riscv-test into kelvin SW project

Use bazel's git_repository functionality to pull RISCV's ISA tests
directly since we are not changing anything from there. The
Kelvin-specific changes are the entry point and the pass/fail condition
(replaced with mpause/ebreak)

Also move the repository dependency into repos.bzl to a cleaner
dependency management.

Change-Id: I21d0c1238d1a5888daee7b23e9b41004c4303752
diff --git a/WORKSPACE b/WORKSPACE
index 60c42e0..1912123 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -1,33 +1,8 @@
 workspace(name = "kelvin")
 
-load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
-load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+load("//build_tools/bazel:repos.bzl", "kelvin_repos")
+kelvin_repos()
 
-# Kelvin toolchain
-new_local_repository(
-    name = "kelvin-gcc",
-    build_file = "third_party/kelvin-gcc/BUILD",
-    path = "../../cache/toolchain_kelvin",
-)
-
-# CRT is the Compiler Repository Toolkit.  It contains the configuration for
-# the windows compiler.
-maybe(
-    http_archive,
-    name = "crt",
-    url = "https://github.com/lowRISC/crt/archive/refs/tags/v0.3.4.tar.gz",
-    sha256 = "01a66778d1a0d5bbfb4ba30e72bd6876d0c20766d0b1921ab36ca3350cb48c60",
-    strip_prefix = "crt-0.3.4",
-)
-
-load("@crt//:repos.bzl", "crt_repos")
-
-crt_repos()
-
-load("@crt//:deps.bzl", "crt_deps")
-
-crt_deps()
-
+# Register Kelvin toolchain
 load("//platforms:registration.bzl", "kelvin_register_toolchain")
-
 kelvin_register_toolchain()
diff --git a/build_tools/bazel/kelvin.bzl b/build_tools/bazel/kelvin.bzl
index 84d037b..ddd20ce 100644
--- a/build_tools/bazel/kelvin.bzl
+++ b/build_tools/bazel/kelvin.bzl
@@ -2,7 +2,6 @@
 
 load("@rules_cc//cc:find_cc_toolchain.bzl", "find_cc_toolchain")
 
-
 KELVIN_PLATFORM = "//platforms/riscv32:kelvin"
 
 def _kelvin_transition_impl(_settings, _attr):
@@ -142,7 +141,11 @@
     toolchains = ["@rules_cc//cc:toolchain_type"],
 )
 
-def kelvin_binary(name, srcs, **kwargs):
+def kelvin_binary(
+        name,
+        srcs,
+        is_riscv_test = False,
+        **kwargs):
     """A helper macro for generating binary artifacts for the kelvin core.
 
     This macro uses the kelvin toolchain, kelvin-specific starting asm,
@@ -151,6 +154,8 @@
     Args:
       name: The name of this rule.
       srcs: The c source files.
+      is_riscv_test: A bool flag to decide if a custom _start asm is included.
+        It is used by riscv-tests.
       **kwargs: Additional arguments forward to cc_binary.
     Emits rules:
       filegroup              named: <name>.bin
@@ -158,11 +163,13 @@
       filegroup              named: <name>.elf
         Containing all elf output for the target.
     """
-    srcs = srcs + [
-        "//crt:kelvin_gloss.cc",
-        "//crt:kelvin_start.S",
-        "//crt:crt.S",
-    ]
+    srcs.append("//crt:kelvin_gloss.cc")
+    if not is_riscv_test:
+        srcs += [
+            "//crt:crt.S",
+            "//crt:kelvin_start.S",
+        ]
+
     kelvin_binary_impl(
         name = name,
         srcs = srcs,
diff --git a/build_tools/bazel/repos.bzl b/build_tools/bazel/repos.bzl
new file mode 100644
index 0000000..7e9cfd6
--- /dev/null
+++ b/build_tools/bazel/repos.bzl
@@ -0,0 +1,34 @@
+"""Kelvin dependency repository setup."""
+
+load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
+load("@bazel_tools//tools/build_defs/repo:git.bzl", "new_git_repository")
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+
+def kelvin_repos():
+    """"Setup Kelvin dependency repositories."""
+
+    # Kelvin toolchain
+    native.new_local_repository(
+        name = "kelvin-gcc",
+        build_file = "third_party/kelvin-gcc/BUILD",
+        path = "../../cache/toolchain_kelvin",
+    )
+
+    # CRT is the Compiler Repository Toolkit.  It contains the configuration for
+    # the windows compiler.
+    maybe(
+        http_archive,
+        name = "crt",
+        url = "https://github.com/lowRISC/crt/archive/refs/tags/v0.3.4.tar.gz",
+        sha256 = "01a66778d1a0d5bbfb4ba30e72bd6876d0c20766d0b1921ab36ca3350cb48c60",
+        strip_prefix = "crt-0.3.4",
+    )
+
+    # risc-v isa test
+    new_git_repository(
+        name = "riscv-tests",
+        commit = "d649367a1386609da3d10e9e6d388f98781dd35f",
+        build_file = "//third_party/riscv:BUILD.riscv-tests",
+        shallow_since = "1636745372 -0800",
+        remote = "https://spacebeaker.googlesource.com/shodan/3p/riscv/riscv-tests",
+    )
diff --git a/tests/riscv-tests/BUILD b/tests/riscv-tests/BUILD
new file mode 100644
index 0000000..1e07424
--- /dev/null
+++ b/tests/riscv-tests/BUILD
@@ -0,0 +1,106 @@
+# Build riscv-tests based on Kelvin linker script and termination condition.
+
+load("//build_tools/bazel:kelvin.bzl", "kelvin_binary")
+
+cc_library(
+    name = "riscv_tests_base",
+    srcs = [
+        "test_main.cc",
+    ],
+    hdrs = [
+        "riscv_test.h",
+        "@riscv-tests//:isa/macros/scalar/test_macros.h",
+    ],
+)
+
+RV32UI_TESTS = [
+    "add",
+    "addi",
+    "and",
+    "andi",
+    "auipc",
+    "beq",
+    "bge",
+    "bgeu",
+    "blt",
+    "bltu",
+    "bne",
+    "fence_i",
+    "jalr",
+    "jal",
+    "lb",
+    "lbu",
+    "lh",
+    "lhu",
+    "lui",
+    "lw",
+    "ori",
+    "or",
+    "sb",
+    "sh",
+    "simple",
+    "slli",
+    "sll",
+    "slti",
+    "sltiu",
+    "slt",
+    "sltu",
+    "srai",
+    "sra",
+    "srli",
+    "srl",
+    "sub",
+    "sw",
+    "xori",
+    "xor",
+]
+
+[kelvin_binary(
+    name = "rv32ui_{}".format(test),
+    srcs = [
+        # riscv-tests use the rv64 code to set up rv32 tests.
+        "@riscv-tests//:isa/rv64ui/{}.S".format(test),
+    ],
+    # The include paths are set explicitly because riscv-tests has special
+    # include dependencies.
+    copts = [
+        "-Itests/riscv-tests",
+        "-Iexternal/riscv-tests/isa/macros/scalar",
+        "-Wno-variadic-macros",
+    ],
+    defines = [
+        "RVTEST_RV64U=RVTEST_RV32U",
+    ],
+    is_riscv_test = True,
+    deps = [
+        ":riscv_tests_base",
+    ],
+) for test in RV32UI_TESTS]
+
+RV32UM_TESTS = [
+    "div",
+    "divu",
+    "mul",
+    "mulh",
+    "mulhsu",
+    "mulhu",
+    "rem",
+    "remu",
+]
+
+[kelvin_binary(
+    name = "rv32um_{}".format(test),
+    srcs = [
+      "@riscv-tests//:isa/rv32um/{}.S".format(test),
+
+    ],
+    copts = [
+        "-Itests/riscv-tests",
+        "-Iexternal/riscv-tests/isa/macros/scalar",
+        "-Wno-variadic-macros",
+    ],
+    is_riscv_test = True,
+    deps = [
+        ":riscv_tests_base",
+    ],
+) for test in RV32UM_TESTS]
diff --git a/tests/riscv-tests/riscv_test.h b/tests/riscv-tests/riscv_test.h
new file mode 100644
index 0000000..9d86895
--- /dev/null
+++ b/tests/riscv-tests/riscv_test.h
@@ -0,0 +1,47 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// A simplified RISCV test header file to replace the pass/fail condition with
+// Kelvin-specific termination calls.
+
+#ifndef TESTS_RISCV_TESTS_RISCV_TEST_H_
+#define TESTS_RISCV_TESTS_RISCV_TEST_H_
+
+#define RVTEST_RV32U \
+  .macro init;       \
+  .endm
+#define RVTEST_CODE_BEGIN \
+  .globl _start;          \
+  _start:
+#define RVTEST_CODE_END
+#define TESTNUM gp
+#define RVTEST_PASS mpause
+#define RVTEST_FAIL ebreak
+#define EXTRA_DATA
+// clang-format off
+#define RVTEST_DATA_BEGIN                                           \
+  EXTRA_DATA                                                        \
+  .pushsection .tohost, "aw", @progbits;                            \
+  .align 6; .global tohost; tohost: .dword 0; .size tohost, 8;      \
+  .align 6; .global fromhost; fromhost: .dword 0; .size fromhost, 8;\
+  .popsection;                                                      \
+  .align 4;                                                         \
+  .global begin_signature;                                          \
+  begin_signature:
+// clang-format on
+#define RVTEST_DATA_END  \
+  .align 4;              \
+  .global end_signature; \
+  end_signature:
+#endif  // TESTS_RISCV_TESTS_RISCV_TEST_H_
diff --git a/tests/riscv-tests/test_main.cc b/tests/riscv-tests/test_main.cc
new file mode 100644
index 0000000..ca87f60
--- /dev/null
+++ b/tests/riscv-tests/test_main.cc
@@ -0,0 +1,21 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Common main test file for riscv ISA tests
+
+extern "C" void _start();
+int main() {
+  _start();
+  return 0;
+}
diff --git a/third_party/riscv/BUILD b/third_party/riscv/BUILD
new file mode 100644
index 0000000..ffd0fb0
--- /dev/null
+++ b/third_party/riscv/BUILD
@@ -0,0 +1 @@
+package(default_visibility = ["//visibility:public"])
diff --git a/third_party/riscv/BUILD.riscv-tests b/third_party/riscv/BUILD.riscv-tests
new file mode 100644
index 0000000..dcf1177
--- /dev/null
+++ b/third_party/riscv/BUILD.riscv-tests
@@ -0,0 +1,8 @@
+package(default_visibility = ["//visibility:public"])
+
+filegroup(
+    name = "all",
+    srcs = glob(["**"], exclude=["**/*.gitignore"]),
+)
+
+exports_files(glob(["**"]))