diff --git a/Makefile b/Makefile index f1f1728..d7bf3c6 100644 --- a/Makefile +++ b/Makefile @@ -25,3 +25,8 @@ clean: .SILENT: run run: all ./$(BUILD_DIR)/$(NAME) + +.PHONY: tests +.SILENT: tests +tests: all + make -C tests diff --git a/README.md b/README.md index 5620154..68267c5 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,12 @@ # vriscv - a risc-v simulator +## Unit tests + +Unit tests can be compiled and run using : +``` +make tests +``` + ## Resources used Juraj's Blog, mostly: diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 0000000..552ee30 --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,22 @@ +AS=riscv32-elf-as +LD=riscv32-elf-ld +BUILD_DIR=../build/tests/ + +S_FILES := $(shell find ./ -name '*.s') +NAMES = $(basename $(S_FILES)) +OBJECTS=$(patsubst %, $(BUILD_DIR)/%, $(NAMES)) + +all: $(OBJECTS) run + +$(BUILD_DIR): + mkdir -p $(BUILD_DIR) + +$(BUILD_DIR)/%.o: %.s | $(BUILD_DIR) + $(AS) $^ -o $@ + +$(BUILD_DIR)/%: $(BUILD_DIR)/%.o | $(BUILD_DIR) + $(LD) $^ -o $@ -nostdlib + +.SILENT: run +run: + bash test.sh diff --git a/tests/addi.s b/tests/addi.s new file mode 100644 index 0000000..6d852f1 --- /dev/null +++ b/tests/addi.s @@ -0,0 +1,4 @@ +.global _start +_start: + addi a0, zero, 0xBA + ebreak diff --git a/tests/beq.s b/tests/beq.s new file mode 100644 index 0000000..4cb9287 --- /dev/null +++ b/tests/beq.s @@ -0,0 +1,31 @@ +.global _start +_start: + # Set base value of a0 to 'test failed' + addi a0, zero, 1 + + # Set A, B values of t0/t1, to test equality + addi t0, zero, 0xA + addi t1, zero, 0xB + beq t0, t1, eq0 + + # Inequality passed, now test equality + addi t0, zero, 0xA + addi t1, zero, 0xA + beq t0, t1, eq1 + + # On failure, return + ebreak + +eqNeg: + # All passed + addi a0, zero, 0 + ebreak + +eq0: + # Inequality failed + ebreak + +eq1: + # Equality passed ; now try to test a negative offset case + beq t0, t1, eqNeg + ebreak diff --git a/tests/jal.s b/tests/jal.s new file mode 100644 index 0000000..6ba76ce --- /dev/null +++ b/tests/jal.s @@ -0,0 +1,21 @@ +.global _start +_start: + # Set base value of a0 to 'test failed' + addi a0, zero, 1 + + # Construct value that ra should have in t0 + auipc t0, 0 + addi t0, t0, 12 + # Jump and link + jal ra, fn0 + ebreak + +fn0: + # Check ra value with our t0 construct + beq t0, ra, eq0 + ebreak + +eq0: + # All good + addi a0, zero, 0 + ebreak diff --git a/tests/jalr.s b/tests/jalr.s new file mode 100644 index 0000000..5100477 --- /dev/null +++ b/tests/jalr.s @@ -0,0 +1,46 @@ +.global _start +_start: + # Set base value of a0 to 'test failed' + addi a0, zero, 1 + + # Setup a stack + addi sp, sp, 0x100 + + # Try to call a simple function + jal fn1 + + # Try to call two imbricated functions + jal fn0 + + auipc t0, 0 + jalr ra, 12(t0) + + ebreak + +# just_after : address is 12 bytes after auipc +just_after: + addi a0, zero, 0 + ret + ebreak + +# fn0 : function that calls fn1 and returns +fn0: + # Make space on the stack + addi sp, sp, -4 + # Save ra + sw ra, 0(sp) + + # Call fn1 + jal fn1 + + # Restore ra and stack + lw ra, 0(sp) + addi sp, sp, 4 + + ret + ebreak + +# fn1 : just return +fn1: + ret + ebreak diff --git a/tests/mv.s b/tests/mv.s new file mode 100644 index 0000000..07b207e --- /dev/null +++ b/tests/mv.s @@ -0,0 +1,5 @@ +.global _start +_start: + addi a1, zero, 0xBA + mv a0, a1 + ebreak diff --git a/tests/swlw.s b/tests/swlw.s new file mode 100644 index 0000000..63f3179 --- /dev/null +++ b/tests/swlw.s @@ -0,0 +1,21 @@ +.global _start +_start: + # Set base value of a0 to 'test failed' + addi a0, zero, 1 + + # Store Word 0xBA at 0x104 + addi t0, zero, 0x100 + addi t1, zero, 0xBA + sw t1, 4(t0) + + # Load Word at 0x104 in t0 + lw t0, 4(t0) + + # Compare + beq t0, t1, good + + ebreak + +good: + addi a0, zero, 0 + ebreak diff --git a/tests/test.sh b/tests/test.sh new file mode 100644 index 0000000..0ef6c91 --- /dev/null +++ b/tests/test.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +GREEN="\e[32m" +RED="\e[31m" +CEND="\e[39m" + +VRISCV=../build/vriscv + +# test executes a test +# Arguments: test(name, executable, expected) +test() { + NAME=$1 + TEST=$2 + RESULT=$3 + + echo -ne "${NAME}""\t\t\t\t\t\t" + $VRISCV $TEST >/dev/null 2>&1 + if [ $? -eq $RESULT ]; then + echo -e $GREEN"PASSED"$CEND + else + echo -e $RED"FAILED"$CEND + fi +} + +test "ADDI : Add Immediate " "../build/tests/addi " 186 +test "MV : Move registers " "../build/tests/mv " 186 +test "BEQ : Branch EQual " "../build/tests/beq " 0 +test "JAL : Jump And Link " "../build/tests/jal " 0 +test "SWLW : Store Word Load Word " "../build/tests/swlw " 0 +test "JALR : Jump And Link Register " "../build/tests/jalr " 0