From: Michael Neuling Date: Tue, 31 Mar 2020 06:32:38 +0000 (+1100) Subject: Add test cases for new exceptions and supervisor state X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=9d7df2d50768df54503dc400e6c774ad82f02c8e;p=microwatt.git Add test cases for new exceptions and supervisor state This adds test cases for: - sc, illegals and decrementer exceptions - decrementer overflow - rfid - mt/mf sprg0/1 srr0/1 - mtdec - mtmsrd - sc It also adds these test cases to make check/check_light Signed-off-by: Michael Neuling --- diff --git a/.gitignore b/.gitignore index 3c7c0b5..776be9b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,7 @@ *.cf *.s *_tb -main_ram.bin \ No newline at end of file +main_ram.bin +tests/*/*.bin +tests/*/*.hex +tests/*/*.elf diff --git a/Makefile b/Makefile index a1658d4..2f90f22 100644 --- a/Makefile +++ b/Makefile @@ -128,14 +128,18 @@ dmi_dtm_tb: dmi_dtm_tb.o sim_vhpi_c.o sim_bram_helpers_c.o $(GHDL) -e $(GHDLFLAGS) -Wl,sim_vhpi_c.o -Wl,sim_bram_helpers_c.o $@ tests = $(sort $(patsubst tests/%.out,%,$(wildcard tests/*.out))) +tests_console = $(sort $(patsubst tests/%.console_out,%,$(wildcard tests/*.console_out))) -check: $(tests) test_micropython test_micropython_long +check: $(tests) $(test_console) test_micropython test_micropython_long -check_light: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 test_micropython test_micropython_long +check_light: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 test_micropython test_micropython_long $(tests_console) $(tests): core_tb @./scripts/run_test.sh $@ +$(tests_console): core_tb + @./scripts/run_test_console.sh $@ + test_micropython: core_tb @./scripts/test_micropython.py diff --git a/scripts/run_test_console.sh b/scripts/run_test_console.sh new file mode 100755 index 0000000..1aaa2bb --- /dev/null +++ b/scripts/run_test_console.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +# Runs a test and checks the console output against known good output + +if [ $# -ne 1 ]; then + echo "Usage: run_test.sh " + exit 1 +fi + +TEST=$1 + +TMPDIR=$(mktemp -d) + +function finish { + rm -rf "$TMPDIR" +} + +trap finish EXIT + +MICROWATT_DIR=$PWD + +cd $TMPDIR + +cp ${MICROWATT_DIR}/tests/${TEST}.bin main_ram.bin + +${MICROWATT_DIR}/core_tb > /dev/null 2> test1.out || true + +grep -v "Failed to bind debug socket" test1.out > test.out + +cp ${MICROWATT_DIR}/tests/${TEST}.console_out exp.out + +cp test.out /tmp +cp exp.out /tmp + +diff -q test.out exp.out && echo "$TEST PASS" && exit 0 + +echo "$TEST FAIL ********" +exit 1 diff --git a/tests/Makefile.test b/tests/Makefile.test new file mode 100644 index 0000000..a043810 --- /dev/null +++ b/tests/Makefile.test @@ -0,0 +1,28 @@ +ARCH = $(shell uname -m) +ifneq ("$(ARCH)", "ppc64") +ifneq ("$(ARCH)", "ppc64le") + CROSS_COMPILE = powerpc64le-linux- + endif + endif + +CC = $(CROSS_COMPILE)gcc +LD = $(CROSS_COMPILE)ld +OBJCOPY = $(CROSS_COMPILE)objcopy + +CFLAGS = -Os -g -Wall -std=c99 -msoft-float -mno-string -mno-multiple -mno-vsx -mno-altivec -mlittle-endian -fno-stack-protector -mstrict-align -ffreestanding -fdata-sections -ffunction-sections -I ../../hello_world +ASFLAGS = $(CFLAGS) +LDFLAGS = -T powerpc.lds + +all: $(TEST).hex + +$(TEST).elf: $(TEST).o head.o ../../hello_world/console.o + $(LD) $(LDFLAGS) -o $(TEST).elf $(TEST).o head.o ../../hello_world/console.o + +$(TEST).bin: $(TEST).elf + $(OBJCOPY) -O binary $(TEST).elf $(TEST).bin + +$(TEST).hex: $(TEST).bin + ../../scripts/bin2hex.py $(TEST).bin > $(TEST).hex + +clean: + @rm -f *.o $(TEST).elf $(TEST).bin $(TEST).hex diff --git a/tests/decrementer/Makefile b/tests/decrementer/Makefile new file mode 100644 index 0000000..2effce5 --- /dev/null +++ b/tests/decrementer/Makefile @@ -0,0 +1,3 @@ +TEST=decrementer + +include ../Makefile.test diff --git a/tests/decrementer/decrementer.c b/tests/decrementer/decrementer.c new file mode 100644 index 0000000..36ac922 --- /dev/null +++ b/tests/decrementer/decrementer.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include + +#include "console.h" + +#define TEST "Test " +#define PASS "PASS\r\n" +#define FAIL "FAIL\r\n" + +extern int dec_test_1(void); +extern int dec_test_2(void); +extern int dec_test_3(void); + +// i < 100 +void print_test_number(int i) +{ + putstr(TEST, strlen(TEST)); + putchar(48 + i/10); + putchar(48 + i%10); + putstr(":", 1); +} + +int main(void) +{ + int fail = 0; + + potato_uart_init(); + + print_test_number(1); + if (dec_test_1() != 0) { + fail = 1; + putstr(FAIL, strlen(FAIL)); + } else + putstr(PASS, strlen(PASS)); + + print_test_number(2); + if (dec_test_2() != 0) { + fail = 1; + putstr(FAIL, strlen(FAIL)); + } else + putstr(PASS, strlen(PASS)); + + + print_test_number(3); + if (dec_test_3() != 0) { + fail = 1; + putstr(FAIL, strlen(FAIL)); + } else + putstr(PASS, strlen(PASS)); + + return fail; +} diff --git a/tests/decrementer/head.S b/tests/decrementer/head.S new file mode 100644 index 0000000..11107ca --- /dev/null +++ b/tests/decrementer/head.S @@ -0,0 +1,161 @@ +/* Copyright 2013-2014 IBM Corp. + * + * 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. + */ + +#define STACK_TOP 0x2000 + +/* Load an immediate 64-bit value into a register */ +#define LOAD_IMM64(r, e) \ + lis r,(e)@highest; \ + ori r,r,(e)@higher; \ + rldicr r,r, 32, 31; \ + oris r,r, (e)@h; \ + ori r,r, (e)@l; + + .section ".head","ax" + + /* + * Microwatt currently enters in LE mode at 0x0, so we don't need to + * do any endian fix ups + */ + . = 0 +.global _start +_start: + b boot_entry + +.global boot_entry +boot_entry: + /* setup stack */ + LOAD_IMM64(%r1, STACK_TOP - 0x100) + LOAD_IMM64(%r12, main) + mtctr %r12 + bctrl + attn // terminate on exit + b . + +/* test to see if end up at the instruction after the rfid */ +.global dec_test_1 +dec_test_1: + li %r3, 0 + mtdec %r3 + LOAD_IMM64(%r3, dec_test_1_rfid) + mtsrr0 %r3 + LOAD_IMM64(%r3, 0x9000000000008003) + mtsrr1 %r3 + li %r3, 1 // preload with a fail code + rfid +dec_test_1_rfid: + b 1f // should be skipped + b 1f // should be skipped + li %r3, 0 + blr +1: + li %r3, 1 + blr + + +/* test to see if end up at the instruction after the rfid */ +.global dec_test_2 +dec_test_2: + li %r3, 0x100 + mtdec %r3 + LOAD_IMM64(%r3, dec_test_2_rfid) + mtsrr0 %r3 + LOAD_IMM64(%r3, 0x9000000000008003) + mtsrr1 %r3 + li %r3, 1 // preload with a fail code + rfid +dec_test_2_rfid: + b . // should wait here and then be skipped + b 1f // should be skipped + li %r3, 0 + blr +1: + li %r3, 1 + blr + + +/* test mtmsrd */ +.global dec_test_3 +dec_test_3: + LOAD_IMM64(%r3, 0x9000000000000003) + mtmsrd %r3 // EE off + li %r3, 0x0 // shouldn't fire right away + mtdec %r3 + b 2f + nop + b 1f // shouln't get here +2: + LOAD_IMM64(%r3, 0x9000000000008003) + mtmsrd %r3 // EE on + b 1f // shouln't get here + b 1f // shouln't get here + + li %r3, 0 + blr +1: + li %r3, 1 + blr + +#define EXCEPTION(nr) \ + .= nr ;\ + b . + + /* More exception stubs */ + EXCEPTION(0x300) + EXCEPTION(0x380) + EXCEPTION(0x400) + EXCEPTION(0x480) + EXCEPTION(0x500) + EXCEPTION(0x600) + EXCEPTION(0x700) + EXCEPTION(0x800) + + . = 0x900 + mtsprg0 %r3 + LOAD_IMM64(%r3, 0x000000000ffffff) + mtdec %r3 + mfsrr0 %r3 + addi %r3, %r3, 8 // skip 2 instructions + mtsrr0 %r3 + mfsprg0 %r3 + rfid + + EXCEPTION(0x980) + EXCEPTION(0xa00) + EXCEPTION(0xb00) + EXCEPTION(0xc00) + EXCEPTION(0xd00) + EXCEPTION(0xe00) + EXCEPTION(0xe20) + EXCEPTION(0xe40) + EXCEPTION(0xe60) + EXCEPTION(0xe80) + EXCEPTION(0xf00) + EXCEPTION(0xf20) + EXCEPTION(0xf40) + EXCEPTION(0xf60) + EXCEPTION(0xf80) +#if 0 + EXCEPTION(0x1000) + EXCEPTION(0x1100) + EXCEPTION(0x1200) + EXCEPTION(0x1300) + EXCEPTION(0x1400) + EXCEPTION(0x1500) + EXCEPTION(0x1600) +#endif + + diff --git a/tests/decrementer/powerpc.lds b/tests/decrementer/powerpc.lds new file mode 100644 index 0000000..0b65470 --- /dev/null +++ b/tests/decrementer/powerpc.lds @@ -0,0 +1,13 @@ +SECTIONS +{ + _start = .; + . = 0; + .head : { + KEEP(*(.head)) + } + . = 0x1000; + .text : { *(.text) } + . = 0x2000; + .data : { *(.data) } + .bss : { *(.bss) } +} diff --git a/tests/illegal/Makefile b/tests/illegal/Makefile new file mode 100644 index 0000000..1c4f392 --- /dev/null +++ b/tests/illegal/Makefile @@ -0,0 +1,3 @@ +TEST=illegal + +include ../Makefile.test diff --git a/tests/illegal/head.S b/tests/illegal/head.S new file mode 100644 index 0000000..5446d68 --- /dev/null +++ b/tests/illegal/head.S @@ -0,0 +1,125 @@ +/* Copyright 2013-2014 IBM Corp. + * + * 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. + */ + +#define STACK_TOP 0x2000 + +/* Load an immediate 64-bit value into a register */ +#define LOAD_IMM64(r, e) \ + lis r,(e)@highest; \ + ori r,r,(e)@higher; \ + rldicr r,r, 32, 31; \ + oris r,r, (e)@h; \ + ori r,r, (e)@l; + + .section ".head","ax" + + /* + * Microwatt currently enters in LE mode at 0x0, so we don't need to + * do any endian fix ups + */ + . = 0 +.global _start +_start: + b boot_entry + +.global boot_entry +boot_entry: + /* setup stack */ + LOAD_IMM64(%r1, STACK_TOP - 0x100) + LOAD_IMM64(%r12, main) + mtctr %r12 + bctrl + attn // terminate on exit + b . + +/* test illegal */ +.global ill_test_1 +ill_test_1: + li %r3, 1 // preload a failure + .long 0x0 // illegal will be skipped + 1 more + b 1f // skipped + + li %r3, 1 // preload a failure + .long 0x0 // illegal will be skipped + 1 more + b 1f // skipped + + li %r3, 0 + blr +1: + li %r3, 1 + blr + +#define EXCEPTION(nr) \ + .= nr ;\ + b . + + /* More exception stubs */ + EXCEPTION(0x300) + EXCEPTION(0x380) + EXCEPTION(0x400) + EXCEPTION(0x480) + EXCEPTION(0x500) + EXCEPTION(0x600) + + . = 0x700 + mtsprg0 %r3 + mtsprg1 %r4 + + // test for bit 44 being set for ILL + mfsrr1 %r3 + li %r4, 1 + sldi %r4, %r4, (63-44) + and. %r4, %r4, %r3 + li %r4, 8 // PASS so skip 2 instructions + bne 1f + li %r4, 4 // FAIL so only skip 1 instruction. Return will catch +1: + mfsrr0 %r3 + add %r3, %r3, %r4 // skip some instructions + mtsrr0 %r3 + + mfsprg0 %r3 + mfsprg1 %r4 + rfid + + EXCEPTION(0x800) + EXCEPTION(0x900) + EXCEPTION(0x980) + EXCEPTION(0xa00) + EXCEPTION(0xb00) + EXCEPTION(0xc00) + EXCEPTION(0xd00) + EXCEPTION(0xe00) + EXCEPTION(0xe20) + EXCEPTION(0xe40) + EXCEPTION(0xe60) + EXCEPTION(0xe80) + EXCEPTION(0xf00) + EXCEPTION(0xf20) + EXCEPTION(0xf40) + EXCEPTION(0xf60) + EXCEPTION(0xf80) +#if 0 + EXCEPTION(0x1000) + EXCEPTION(0x1100) + EXCEPTION(0x1200) + EXCEPTION(0x1300) + EXCEPTION(0x1400) + EXCEPTION(0x1500) + EXCEPTION(0x1600) +#endif + + diff --git a/tests/illegal/illegal.c b/tests/illegal/illegal.c new file mode 100644 index 0000000..0778ffe --- /dev/null +++ b/tests/illegal/illegal.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include + +#include "console.h" + +#define TEST "Test " +#define PASS "PASS\r\n" +#define FAIL "FAIL\r\n" + +extern int ill_test_1(void); + +// i < 100 +void print_test_number(int i) +{ + putstr(TEST, strlen(TEST)); + putchar(48 + i/10); + putchar(48 + i%10); + putstr(":", 1); +} + +int main(void) +{ + int fail = 0; + + potato_uart_init(); + + print_test_number(1); + if (ill_test_1() != 0) { + fail = 1; + putstr(FAIL, strlen(FAIL)); + } else + putstr(PASS, strlen(PASS)); + + return fail; +} diff --git a/tests/illegal/powerpc.lds b/tests/illegal/powerpc.lds new file mode 100644 index 0000000..0b65470 --- /dev/null +++ b/tests/illegal/powerpc.lds @@ -0,0 +1,13 @@ +SECTIONS +{ + _start = .; + . = 0; + .head : { + KEEP(*(.head)) + } + . = 0x1000; + .text : { *(.text) } + . = 0x2000; + .data : { *(.data) } + .bss : { *(.bss) } +} diff --git a/tests/sc/Makefile b/tests/sc/Makefile new file mode 100644 index 0000000..a2fb869 --- /dev/null +++ b/tests/sc/Makefile @@ -0,0 +1,3 @@ +TEST=sc + +include ../Makefile.test diff --git a/tests/sc/head.S b/tests/sc/head.S new file mode 100644 index 0000000..ddbedef --- /dev/null +++ b/tests/sc/head.S @@ -0,0 +1,111 @@ +/* Copyright 2013-2014 IBM Corp. + * + * 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. + */ + +#define STACK_TOP 0x2000 + +/* Load an immediate 64-bit value into a register */ +#define LOAD_IMM64(r, e) \ + lis r,(e)@highest; \ + ori r,r,(e)@higher; \ + rldicr r,r, 32, 31; \ + oris r,r, (e)@h; \ + ori r,r, (e)@l; + + .section ".head","ax" + + /* + * Microwatt currently enters in LE mode at 0x0, so we don't need to + * do any endian fix ups + */ + . = 0 +.global _start +_start: + b boot_entry + +.global boot_entry +boot_entry: + /* setup stack */ + LOAD_IMM64(%r1, STACK_TOP - 0x100) + LOAD_IMM64(%r12, main) + mtctr %r12 + bctrl + attn // terminate on exit + b . + +/* test sc */ +.global sc_test_1 +sc_test_1: + li %r3, 1 // preload a failure + sc + b 1f // skipped + b 1f // skipped + b 2f // return here is good! + b 1f // shouldn't hit here +2: + li %r3, 0 + blr +1: + li %r3, 1 + blr + +#define EXCEPTION(nr) \ + .= nr ;\ + b . + + /* More exception stubs */ + EXCEPTION(0x300) + EXCEPTION(0x380) + EXCEPTION(0x400) + EXCEPTION(0x480) + EXCEPTION(0x500) + EXCEPTION(0x600) + EXCEPTION(0x700) + EXCEPTION(0x800) + EXCEPTION(0x900) + EXCEPTION(0x980) + EXCEPTION(0xa00) + EXCEPTION(0xb00) + + . = 0xc00 + mtsprg0 %r3 + mfsrr0 %r3 + addi %r3, %r3, 8 // skip 2 instructions + mtsrr0 %r3 + mfsprg0 %r3 + rfid + + EXCEPTION(0xd00) + EXCEPTION(0xe00) + EXCEPTION(0xe20) + EXCEPTION(0xe40) + EXCEPTION(0xe60) + EXCEPTION(0xe80) + EXCEPTION(0xf00) + EXCEPTION(0xf20) + EXCEPTION(0xf40) + EXCEPTION(0xf60) + EXCEPTION(0xf80) +#if 0 + EXCEPTION(0x1000) + EXCEPTION(0x1100) + EXCEPTION(0x1200) + EXCEPTION(0x1300) + EXCEPTION(0x1400) + EXCEPTION(0x1500) + EXCEPTION(0x1600) +#endif + + diff --git a/tests/sc/powerpc.lds b/tests/sc/powerpc.lds new file mode 100644 index 0000000..0b65470 --- /dev/null +++ b/tests/sc/powerpc.lds @@ -0,0 +1,13 @@ +SECTIONS +{ + _start = .; + . = 0; + .head : { + KEEP(*(.head)) + } + . = 0x1000; + .text : { *(.text) } + . = 0x2000; + .data : { *(.data) } + .bss : { *(.bss) } +} diff --git a/tests/sc/sc.c b/tests/sc/sc.c new file mode 100644 index 0000000..67d80b9 --- /dev/null +++ b/tests/sc/sc.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include + +#include "console.h" + +#define TEST "Test " +#define PASS "PASS\r\n" +#define FAIL "FAIL\r\n" + +extern int sc_test_1(void); + +// i < 100 +void print_test_number(int i) +{ + putstr(TEST, strlen(TEST)); + putchar(48 + i/10); + putchar(48 + i%10); + putstr(":", 1); +} + +int main(void) +{ + int fail = 0; + + potato_uart_init(); + + print_test_number(1); + if (sc_test_1() != 0) { + fail = 1; + putstr(FAIL, strlen(FAIL)); + } else + putstr(PASS, strlen(PASS)); + + return fail; +} diff --git a/tests/test_decrementer.bin b/tests/test_decrementer.bin new file mode 100755 index 0000000..9524469 Binary files /dev/null and b/tests/test_decrementer.bin differ diff --git a/tests/test_decrementer.console_out b/tests/test_decrementer.console_out new file mode 100644 index 0000000..e70abe3 --- /dev/null +++ b/tests/test_decrementer.console_out @@ -0,0 +1,3 @@ +Test 01:PASS +Test 02:PASS +Test 03:PASS diff --git a/tests/test_illegal.bin b/tests/test_illegal.bin new file mode 100755 index 0000000..dac5b01 Binary files /dev/null and b/tests/test_illegal.bin differ diff --git a/tests/test_illegal.console_out b/tests/test_illegal.console_out new file mode 100644 index 0000000..f954c28 --- /dev/null +++ b/tests/test_illegal.console_out @@ -0,0 +1 @@ +Test 01:PASS diff --git a/tests/test_sc.bin b/tests/test_sc.bin new file mode 100755 index 0000000..5af07be Binary files /dev/null and b/tests/test_sc.bin differ diff --git a/tests/test_sc.console_out b/tests/test_sc.console_out new file mode 100644 index 0000000..f954c28 --- /dev/null +++ b/tests/test_sc.console_out @@ -0,0 +1 @@ +Test 01:PASS diff --git a/tests/update_console_tests b/tests/update_console_tests new file mode 100755 index 0000000..c17c12b --- /dev/null +++ b/tests/update_console_tests @@ -0,0 +1,14 @@ +#!/bin/bash +# +# Script to update console related tests from source +# + +for i in sc illegal decrementer ; do + cd $i + make + cd - + cp $i/$i.bin test_$i.bin + ln -s test_$i.bin main_ram.bin + ../core_tb > /dev/null 2> test_$i.console_out + rm main_ram.bin +done