Add test cases for triggering program faults
- Adds a set of test cases that do things like illegal instructions,
load/store faults, misaligned execution, etc.
- Minor changes to build rules to allow tests to "fail successfully",
and to allow specifying which sims to run on, instead of
unconditionally running on all sims.
Change-Id: Ie0ae0bf20ed28a610c969e7d8bbb482ce5f69224
diff --git a/build_tools/bazel/kelvin.bzl b/build_tools/bazel/kelvin.bzl
index c29614a..484afc4 100644
--- a/build_tools/bazel/kelvin.bzl
+++ b/build_tools/bazel/kelvin.bzl
@@ -208,6 +208,9 @@
hw_test_tags = [],
iss_test_size = "small",
iss_test_tags = [],
+ expect_success = True,
+ hw = True,
+ iss = True,
**kwargs):
"""A sh_test wrapper for kelvin binaries
@@ -230,42 +233,46 @@
**kwargs
)
+ tests = []
+
iss_test = "{}_iss".format(name)
- native.sh_test(
- name = iss_test,
- size = iss_test_size,
- srcs = [
- "@kelvin_sw//build_tools:test_runner.sh",
- ],
- args = [
- "$(location %s.elf)" % kelvin_elf,
- ],
- data = [
- "{}.elf".format(kelvin_elf),
- ],
- tags = ["iss"] + iss_test_tags + tags,
- )
+ if iss:
+ native.sh_test(
+ name = iss_test,
+ size = iss_test_size,
+ srcs = [
+ "@kelvin_sw//build_tools:test_runner.sh",
+ ],
+ args = [
+ "$(location %s.elf)" % kelvin_elf,
+ ],
+ data = [
+ "{}.elf".format(kelvin_elf),
+ ],
+ tags = ["iss"] + iss_test_tags + tags,
+ )
+ tests.append(iss_test)
hw_test = "{}_hw".format(name)
- native.sh_test(
- name = hw_test,
- size = hw_test_size,
- srcs = ["@kelvin_sw//build_tools:core_sim_test_runner.sh"],
- args = [
- "$(location %s.bin)" % kelvin_elf,
- ],
- data = [
- "{}.bin".format(kelvin_elf),
- ],
- tags = ["systemc"] + hw_test_tags + tags,
- )
+ if hw:
+ native.sh_test(
+ name = hw_test,
+ size = hw_test_size,
+ srcs = ["@kelvin_sw//build_tools:core_sim_test_runner.sh"],
+ args = [
+ "$(location %s.bin)" % kelvin_elf,
+ str(expect_success),
+ ],
+ data = [
+ "{}.bin".format(kelvin_elf),
+ ],
+ tags = ["systemc"] + hw_test_tags + tags,
+ )
+ tests.append(hw_test)
native.test_suite(
name = name,
- tests = [
- iss_test,
- hw_test,
- ],
+ tests = tests,
tags = tags
)
diff --git a/build_tools/core_sim_test_runner.sh b/build_tools/core_sim_test_runner.sh
index eb3ad5a..2d5b029 100755
--- a/build_tools/core_sim_test_runner.sh
+++ b/build_tools/core_sim_test_runner.sh
@@ -16,7 +16,7 @@
# Test runner for SystemC simulator. Note the input should be the .bin file.
function print_usage {
- echo "Usage: core_sim_test_runner.sh <bin location> [extra flags]"
+ echo "Usage: core_sim_test_runner.sh <bin location> <expected result>"
}
if [[ $1 == "--help" ]]; then
@@ -42,8 +42,19 @@
BIN_FILE=$(realpath $1)
shift 1
-SIM_OUT=$(${CORE_SIM} "${BIN_FILE}" $@)
+EXPECTED_RESULT=${1:-True}
+shift 1
+
+SIM_OUT=$(${CORE_SIM} "${BIN_FILE}")
RESULT=$?
echo "${SIM_OUT}"
-exit ${RESULT}
+if [[ "${EXPECTED_RESULT}" == "True" ]]; then
+ exit ${RESULT}
+elif [[ "${EXPECTED_RESULT}" == "False" ]]; then
+ if [[ ${RESULT} -eq 0 ]]; then
+ exit -1
+ else
+ exit 0
+ fi
+fi
diff --git a/crt/kelvin_tcm.ld b/crt/kelvin_tcm.ld
index b498a59..b24c11a 100644
--- a/crt/kelvin_tcm.ld
+++ b/crt/kelvin_tcm.ld
@@ -24,10 +24,12 @@
.init.array : ALIGN(16) {
__init_array_start = .;
+ __init_array_start__ = .;
*(.init_array)
*(.init_array.*)
. = ALIGN(16);
__init_array_end = .;
+ __init_array_end__ = .;
} > ITCM
.rodata : ALIGN(16) {
@@ -52,6 +54,11 @@
*(.sdata.*)
*(.data)
*(.data.*)
+ /**
+ * Memory location for the return value from main,
+ * which could be inspected by another core in the system.
+ **/
+ _ret = .;
. = ALIGN(16);
__data_end__ = .;
} > DTCM
diff --git a/tests/kelvin_isa/BUILD b/tests/kelvin_isa/BUILD
index 5861d6a..dabb7d2 100644
--- a/tests/kelvin_isa/BUILD
+++ b/tests/kelvin_isa/BUILD
@@ -33,6 +33,7 @@
deps = [
":kelvin_test",
],
+ tags = ["tcm-incompatible"],
)
kelvin_test(
@@ -47,6 +48,132 @@
)
kelvin_test(
+ name = "instr_fault",
+ srcs = [
+ "instr_fault.cc",
+ ],
+ hw_test_size = "small",
+ deps = [
+ ":kelvin_test",
+ ],
+ iss = False,
+ expect_success = False,
+ tags = ["intentional_failure"],
+)
+
+kelvin_test(
+ name = "illegal",
+ srcs = [
+ "illegal.cc",
+ ],
+ hw_test_size = "small",
+ deps = [
+ ":kelvin_test",
+ ],
+ iss = False,
+ expect_success = False,
+ tags = ["intentional_failure"],
+)
+
+kelvin_test(
+ name = "instr_align_0",
+ srcs = [
+ "instr_align_0.cc",
+ ],
+ hw_test_size = "small",
+ deps = [
+ ":kelvin_test",
+ ],
+ iss = False,
+ expect_success = False,
+ tags = ["intentional_failure"],
+)
+
+kelvin_test(
+ name = "instr_align_1",
+ srcs = [
+ "instr_align_1.cc",
+ ],
+ hw_test_size = "small",
+ deps = [
+ ":kelvin_test",
+ ],
+ iss = False,
+ expect_success = False,
+ tags = ["intentional_failure"],
+)
+
+kelvin_test(
+ name = "instr_align_2",
+ srcs = [
+ "instr_align_2.cc",
+ ],
+ hw_test_size = "small",
+ deps = [
+ ":kelvin_test",
+ ],
+ iss = False,
+ expect_success = False,
+ tags = ["intentional_failure"],
+)
+
+kelvin_test(
+ name = "load_fault_0",
+ srcs = [
+ "load_fault_0.cc",
+ ],
+ hw_test_size = "small",
+ deps = [
+ ":kelvin_test",
+ ],
+ iss = False,
+ expect_success = False,
+ tags = ["intentional_failure"],
+)
+
+kelvin_test(
+ name = "load_fault_1",
+ srcs = [
+ "load_fault_1.cc",
+ ],
+ hw_test_size = "small",
+ deps = [
+ ":kelvin_test",
+ ],
+ iss = False,
+ expect_success = False,
+ tags = ["intentional_failure"],
+)
+
+kelvin_test(
+ name = "store_fault_0",
+ srcs = [
+ "store_fault_0.cc",
+ ],
+ hw_test_size = "small",
+ deps = [
+ ":kelvin_test",
+ ],
+ iss = False,
+ # This passes on core_sim, but should fail on core_mini_sim.
+ # expect_success = False,
+)
+
+kelvin_test(
+ name = "store_fault_1",
+ srcs = [
+ "store_fault_1.cc",
+ ],
+ hw_test_size = "small",
+ deps = [
+ ":kelvin_test",
+ ],
+ iss = False,
+ expect_success = False,
+ tags = ["intentional_failure"],
+)
+
+kelvin_test(
name = "acset",
srcs = [
"acset.cc",
@@ -55,6 +182,7 @@
deps = [
":kelvin_test",
],
+ tags = ["tcm-incompatible"],
)
kelvin_test(
@@ -66,6 +194,7 @@
deps = [
":kelvin_test",
],
+ tags = ["tcm-incompatible"],
)
kelvin_test(
@@ -79,6 +208,7 @@
deps = [
":kelvin_test",
],
+ tags = ["tcm-incompatible"],
)
kelvin_test(
@@ -89,6 +219,7 @@
deps = [
":kelvin_test",
],
+ tags = ["tcm-incompatible"],
)
kelvin_test(
@@ -99,6 +230,7 @@
deps = [
":kelvin_test",
],
+ tags = ["tcm-incompatible"],
)
kelvin_test(
@@ -109,6 +241,7 @@
deps = [
":kelvin_test",
],
+ tags = ["tcm-incompatible"],
)
kelvin_test(
@@ -119,6 +252,7 @@
deps = [
":kelvin_test",
],
+ tags = ["tcm-incompatible"],
)
kelvin_test(
@@ -129,6 +263,7 @@
deps = [
":kelvin_test",
],
+ tags = ["tcm-incompatible"],
)
cc_library(
@@ -147,6 +282,7 @@
":kelvin_test",
":vdwconv_data",
],
+ tags = ["tcm-incompatible"],
)
kelvin_test(
@@ -157,6 +293,7 @@
deps = [
":kelvin_test",
],
+ tags = ["tcm-incompatible"],
)
kelvin_test(
@@ -167,6 +304,7 @@
deps = [
":kelvin_test",
],
+ tags = ["tcm-incompatible"],
)
kelvin_test(
@@ -177,6 +315,7 @@
deps = [
":kelvin_test",
],
+ tags = ["tcm-incompatible"],
)
kelvin_test(
@@ -188,6 +327,7 @@
deps = [
":kelvin_test",
],
+ tags = ["tcm-incompatible"],
)
kelvin_test(
@@ -199,6 +339,7 @@
deps = [
":kelvin_test",
],
+ tags = ["tcm-incompatible"],
)
kelvin_test(
@@ -210,6 +351,7 @@
deps = [
":kelvin_test",
],
+ tags = ["tcm-incompatible"],
)
kelvin_test(
@@ -220,6 +362,7 @@
deps = [
":kelvin_test",
],
+ tags = ["tcm-incompatible"],
)
kelvin_test(
@@ -230,6 +373,7 @@
deps = [
":kelvin_test",
],
+ tags = ["tcm-incompatible"],
)
kelvin_test(
@@ -240,6 +384,7 @@
deps = [
":kelvin_test",
],
+ tags = ["tcm-incompatible"],
)
kelvin_test(
@@ -250,6 +395,7 @@
deps = [
":kelvin_test",
],
+ tags = ["tcm-incompatible"],
)
kelvin_test(
@@ -260,6 +406,7 @@
deps = [
":kelvin_test",
],
+ tags = ["tcm-incompatible"],
)
kelvin_test(
@@ -271,4 +418,5 @@
deps = [
":kelvin_test",
],
+ tags = ["tcm-incompatible"],
)
diff --git a/tests/kelvin_isa/illegal.cc b/tests/kelvin_isa/illegal.cc
new file mode 100644
index 0000000..418ee00
--- /dev/null
+++ b/tests/kelvin_isa/illegal.cc
@@ -0,0 +1,21 @@
+// Copyright 2024 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.
+
+#include <cstdint>
+
+int main(int argc, char** argv) {
+ asm volatile(".word 0x02007043"); // fmadd.d f0, f0, f0, f0
+
+ return 0;
+}
diff --git a/tests/kelvin_isa/instr_align_0.cc b/tests/kelvin_isa/instr_align_0.cc
new file mode 100644
index 0000000..303e279
--- /dev/null
+++ b/tests/kelvin_isa/instr_align_0.cc
@@ -0,0 +1,22 @@
+// Copyright 2024 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.
+
+#include <cstdint>
+
+int main(int argc, char** argv) {
+ // Instruction address misaligned
+ asm volatile("la ra, 0x3; jalr ra,ra");
+
+ return 0;
+}
diff --git a/tests/kelvin_isa/instr_align_1.cc b/tests/kelvin_isa/instr_align_1.cc
new file mode 100644
index 0000000..1ee81d1
--- /dev/null
+++ b/tests/kelvin_isa/instr_align_1.cc
@@ -0,0 +1,22 @@
+// Copyright 2024 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.
+
+#include <cstdint>
+
+int main(int argc, char** argv) {
+ // Instruction address misaligned
+ asm volatile("jal x0, .+2");
+
+ return 0;
+}
diff --git a/tests/kelvin_isa/instr_align_2.cc b/tests/kelvin_isa/instr_align_2.cc
new file mode 100644
index 0000000..21aa0b7
--- /dev/null
+++ b/tests/kelvin_isa/instr_align_2.cc
@@ -0,0 +1,22 @@
+// Copyright 2024 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.
+
+#include <cstdint>
+
+int main(int argc, char** argv) {
+ // Instruction address misaligned
+ asm volatile("beqz x0, .+2");
+
+ return 0;
+}
diff --git a/tests/kelvin_isa/instr_fault.cc b/tests/kelvin_isa/instr_fault.cc
new file mode 100644
index 0000000..c3e974f
--- /dev/null
+++ b/tests/kelvin_isa/instr_fault.cc
@@ -0,0 +1,19 @@
+// Copyright 2024 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.
+
+int main(int argc, char** argv) {
+ asm volatile("la ra, 0x40000000; jalr ra, ra");
+
+ return 0;
+}
diff --git a/tests/kelvin_isa/load_fault_0.cc b/tests/kelvin_isa/load_fault_0.cc
new file mode 100644
index 0000000..c3e974f
--- /dev/null
+++ b/tests/kelvin_isa/load_fault_0.cc
@@ -0,0 +1,19 @@
+// Copyright 2024 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.
+
+int main(int argc, char** argv) {
+ asm volatile("la ra, 0x40000000; jalr ra, ra");
+
+ return 0;
+}
diff --git a/tests/kelvin_isa/load_fault_1.cc b/tests/kelvin_isa/load_fault_1.cc
new file mode 100644
index 0000000..78f7beb
--- /dev/null
+++ b/tests/kelvin_isa/load_fault_1.cc
@@ -0,0 +1,23 @@
+// Copyright 2024 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.
+
+#include <cstdint>
+
+int main(int argc, char** argv) {
+ volatile uint32_t* load_bad_addr = (uint32_t*)0xA0000000;
+ volatile uint32_t foo = *load_bad_addr;
+ (void)foo;
+
+ return 0;
+}
diff --git a/tests/kelvin_isa/store_fault_0.cc b/tests/kelvin_isa/store_fault_0.cc
new file mode 100644
index 0000000..68c5094
--- /dev/null
+++ b/tests/kelvin_isa/store_fault_0.cc
@@ -0,0 +1,23 @@
+// Copyright 2024 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.
+
+#include <cstdint>
+
+int main(int argc, char** argv) {
+ // Store Fault (internal)
+ volatile uint32_t* store_bad_addr = (uint32_t*)4L;
+ *store_bad_addr = 0xdeadbeef;
+
+ return 0;
+}
diff --git a/tests/kelvin_isa/store_fault_1.cc b/tests/kelvin_isa/store_fault_1.cc
new file mode 100644
index 0000000..bb5d2fc
--- /dev/null
+++ b/tests/kelvin_isa/store_fault_1.cc
@@ -0,0 +1,23 @@
+// Copyright 2024 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.
+
+#include <cstdint>
+
+int main(int argc, char** argv) {
+ // Store Fault (external)
+ volatile uint32_t* store_bad_addr = (uint32_t*)0xA0000000;
+ *store_bad_addr = 0xdeadbeef;
+
+ return 0;
+}