Enable unit test simulation

Add a sh_test wrapper to enable unit test simulation via bazel test

Change-Id: Ic39fb082c4613b28b5af06858f95de7f36e45d61
diff --git a/README.md b/README.md
index 6c95545..bdd0cf8 100644
--- a/README.md
+++ b/README.md
@@ -37,6 +37,12 @@
 bazel build //...
 ```
 
+To run the unit tests (with the kelvin_sim ISS)
+
+```bash
+bazel test --test_env=ROOTDIR=${ROOTDIR} //...
+```
+
 ### CMake
 
 ```note
@@ -45,8 +51,12 @@
 
 ## Run the executable
 
+The binaries can be simulated with the kelvin simulator, located at
+`<dir>/sim/kelvin`.
+
 ```note
-TODO: Add kelvin simulator
+sim_kelvin <elf location>
 ```
 
-Load the generated `.bin` binaries to matcha FPGA emulator.
+Load the generated `.bin` binaries to the FPGA emulator/Renode simulator.
+
diff --git a/build_tools/BUILD b/build_tools/BUILD
new file mode 100644
index 0000000..d53f03c
--- /dev/null
+++ b/build_tools/BUILD
@@ -0,0 +1,5 @@
+package(default_visibility = ["//visibility:public"])
+
+exports_files([
+    "test_runner.sh",
+])
diff --git a/build_tools/bazel/kelvin.bzl b/build_tools/bazel/kelvin.bzl
index f3f39aa..6f7596d 100644
--- a/build_tools/bazel/kelvin.bzl
+++ b/build_tools/bazel/kelvin.bzl
@@ -189,3 +189,37 @@
         srcs = [name],
         output_group = "elf_file",
     )
+
+def kelvin_test(
+        name,
+        size = "small",
+        **kwargs):
+    """A sh_test wrapper for kelvin binaries
+
+    A wrapper to build kelvin_binary and test it against build_tools/test_runner.sh
+
+    Args:
+      name: The name of this rule.
+      size: Test size. Default to small.
+      **kwargs: Agruments that will be forwarded to kelvin_binary
+    """
+
+    kelvin_elf = "{}_elf".format(name)
+    kelvin_binary(
+        name = kelvin_elf,
+        **kwargs
+    )
+
+    native.sh_test(
+        name = name,
+        size = size,
+        srcs = [
+            "//build_tools:test_runner.sh",
+        ],
+        args = [
+            "$(location %s.elf)" % kelvin_elf,
+        ],
+        data = [
+            "{}.elf".format(kelvin_elf),
+        ],
+    )
diff --git a/build_tools/test_runner.sh b/build_tools/test_runner.sh
new file mode 100755
index 0000000..822606b
--- /dev/null
+++ b/build_tools/test_runner.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+function print_usage {
+  echo "Usage: test_runner.sh <elf location>"
+}
+
+if [[ $1 == "--help" ]]; then
+  print_usage
+fi
+
+if [[ -z ${ROOTDIR} ]]; then
+  echo "Please run \"source build/setup.sh\" first"
+  exit 1
+fi
+
+if [[ ! -f ${ROOTDIR}/out/kelvin/sim/kelvin_sim ]]; then
+  echo "Please run \"m kelvin_sim\" first"
+  exit 1
+fi
+
+if (( $# != 1 )); then
+  print_usage
+  exit 1
+fi
+
+ELF_FILE=$(realpath $1)
+SIM_OUT=$(${ROOTDIR}/out/kelvin/sim/kelvin_sim "${ELF_FILE}")
+echo "${SIM_OUT}"
+if [[ ! "${SIM_OUT}" == *"Program exits properly"* ]]; then
+  exit 1
+fi
+
diff --git a/tests/kelvin_isa/BUILD b/tests/kelvin_isa/BUILD
index 610ad28..a129b68 100644
--- a/tests/kelvin_isa/BUILD
+++ b/tests/kelvin_isa/BUILD
@@ -1,17 +1,17 @@
-load("//build_tools/bazel:kelvin.bzl", "kelvin_binary")
+load("//build_tools/bazel:kelvin.bzl", "kelvin_test")
 
-kelvin_binary(
-  name = "getvl_test",
-  srcs = [
-    "getvl_test.cc",
-  ],
-  hdrs = [
-    "kelvin_test.h",
-  ],
-  copts = [
-    "-Wno-address",
-  ],
-  deps = [
-    "//crt:crt_header",
-  ]
+kelvin_test(
+    name = "getvl_test",
+    srcs = [
+        "getvl_test.cc",
+    ],
+    hdrs = [
+        "kelvin_test.h",
+    ],
+    copts = [
+        "-Wno-address",
+    ],
+    deps = [
+        "//crt:crt_header",
+    ],
 )
diff --git a/tests/riscv-tests/BUILD b/tests/riscv-tests/BUILD
index a6cc677..2b8f273 100644
--- a/tests/riscv-tests/BUILD
+++ b/tests/riscv-tests/BUILD
@@ -1,6 +1,6 @@
 # Build riscv-tests based on Kelvin linker script and termination condition.
 
-load("//build_tools/bazel:kelvin.bzl", "kelvin_binary")
+load("//build_tools/bazel:kelvin.bzl", "kelvin_test")
 
 cc_library(
     name = "riscv_tests_base",
@@ -58,7 +58,7 @@
     "xor",
 ]
 
-[kelvin_binary(
+[kelvin_test(
     name = "rv32ui_{}".format(test),
     srcs = [
         # riscv-tests use the rv64 code to set up rv32 tests.
@@ -91,7 +91,7 @@
     "remu",
 ]
 
-[kelvin_binary(
+[kelvin_test(
     name = "rv32um_{}".format(test),
     srcs = [
         "@riscv-tests//:isa/rv32um/{}.S".format(test),
@@ -107,7 +107,7 @@
     ],
 ) for test in RV32UM_TESTS]
 
-kelvin_binary(
+kelvin_test(
     name = "branch_modulo_test",
     srcs = [
         "branch_modulo_test.cc",
@@ -117,7 +117,7 @@
     ],
 )
 
-kelvin_binary(
+kelvin_test(
     name = "branch_div_test",
     srcs = [
         "branch_div_test.cc",