diff --git a/.gitmodules b/.gitmodules index 7e5c9953..03d9f1b9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,6 @@ [submodule "extern/sail-riscv"] path = extern/sail-riscv url = https://github.com/rems-project/sail-riscv.git +[submodule "extern/riscv-compliance"] + path = extern/riscv-compliance + url = https://github.com/riscv/riscv-compliance.git diff --git a/bin/conf.sh b/bin/conf.sh index 7d5c67c8..5a96bbb9 100644 --- a/bin/conf.sh +++ b/bin/conf.sh @@ -24,12 +24,19 @@ if [ -z $RISCV_ARCH ] ; then fi export RISCV=$REPO_BUILD/$RISCV_ARCH +export SAIL_RISCV=$REPO_HOME/extern/sail-riscv + +[[ ":$PATH:" != *":$RISCV/bin:"* ]] && export PATH="${RISCV}/bin:${PATH}" +[[ ":$PATH:" != *":$SAIL_RISCV/c_emulator:"* ]] && export PATH="$SAIL_RISCV/c_emulator:${PATH}" +[[ ":$PATH:" != *":$SAIL_RISCV/ocaml_emulator:"* ]] && export PATH="$SAIL_RISCV/ocaml_emulator:${PATH}" echo "REPO_HOME = $REPO_HOME" echo "REPO_BUILD = $REPO_BUILD" echo "RISCV_ARCH = $RISCV_ARCH" echo "RISCV = $RISCV" echo "YOSYS_ROOT = $YOSYS_ROOT" +echo "SAIL_RISCV = $SAIL_RISCV" +echo "PATH = $PATH" echo "------------------------------" diff --git a/extern/riscv-compliance b/extern/riscv-compliance new file mode 160000 index 00000000..207bc4e3 --- /dev/null +++ b/extern/riscv-compliance @@ -0,0 +1 @@ +Subproject commit 207bc4e3ac3af94fd6759aa9bed7a241692c101c diff --git a/tests/compliance/Makefile b/tests/compliance/Makefile new file mode 100644 index 00000000..2d517d15 --- /dev/null +++ b/tests/compliance/Makefile @@ -0,0 +1,34 @@ + +ifndef REPO_HOME + $(error "Please run 'source ./bin/conf.sh' to setup the project workspace") +endif + +COMPLIANCE_REPO=$(REPO_HOME)/extern/riscv-compliance +COMPLIANCE_PATCH=$(REPO_HOME)/tests/compliance/riscv-compliance.patch + +compliance-revert-patch: + cd $(COMPLIANCE_REPO) && git reset HEAD && git checkout . && git clean -dxf + +compliance-apply-patch: + cd $(COMPLIANCE_REPO) && git apply $(COMPLIANCE_PATCH) + cd $(COMPLIANCE_REPO) && git add . + +compliance-update-patch: + cd $(COMPLIANCE_REPO) && git diff --cached > $(COMPLIANCE_PATCH) + + +compliance-run-spike: + $(MAKE) -C $(COMPLIANCE_REPO) RISCV_PREFIX=riscv64-unknown-elf \ + RISCV_TARGET=spike + +compliance-run-sail-csim: + $(MAKE) -C $(COMPLIANCE_REPO) RISCV_PREFIX=riscv64-unknown-elf \ + RISCV_TARGET=sail-riscv-c + +compliance-run-sail-ocaml: + $(MAKE) -C $(COMPLIANCE_REPO) RISCV_PREFIX=riscv64-unknown-elf \ + RISCV_TARGET=sail-riscv-ocaml + +compliance-run-all: compliance-run-spike \ + compliance-run-sail-csim \ + compliance-run-sail-ocaml diff --git a/tests/compliance/README.md b/tests/compliance/README.md new file mode 100644 index 00000000..fd20f147 --- /dev/null +++ b/tests/compliance/README.md @@ -0,0 +1,94 @@ + +# RISC-V Crypto Compliance Tests + +*Work in progress compliance test development framework.* + +--- + +## Useful Links + +- [RISC-V Compliance Github Repo](https://github.com/riscv/riscv-compliance) + - [Documentation](https://github.com/riscv/riscv-compliance/tree/master/doc) + + +## Getting Started + +- Make sure that you are in the root of the `riscv-crypto` repository, and + run the workspace setup script: + + ``` + source bin/conf.sh + ``` + + This makes sure that the `spike` and `sail` simulators (if they are + built) are in the `$PATH`, which is needed by the compliance framework. + +- Ensure the riscv-compliance sub-module is checked out: + + ``` + git submodule update --init extern/riscv-compliance + ``` + +- The compliance tests are currently maintained as a patch to a known-good + commit of the riscv-compliance repository. + Once the riscv-compliance repo submodule is checked out, the following + commands can be used to manage the patch. + + - Apply the patch to the submodule: + + ``` + make -C tests/compliance compliance-apply-patch + ``` + + This applies the `tests/compliance/riscv-compliance.patch` to + the submodule, and stages the modifications. + + - Revert the patch: + + ``` + make -C tests/compliance compliance-revert-patch + ``` + + This puts the riscv-compliance sub-module pack to an un-modified state. + + - Update the patch: + + ``` + make -C tests/compliance compliance-update-patch + ``` + + This takes all of the *staged* changes in the riscv-compliance + submodule, and updates the patch file in the riscv-crypto + repository. + + +## Running the compliance tests + +- Run: + + ```make + make -C extern/riscv-compliance RISCV_TARGET= RISCV_DEVICE= RISCV_PREFIX=riscv64-unknown-elf + ``` + + Where: + + - `target` is one of `spike`, `sail-riscv-c` or `sail-riscv-ocaml` + + and + + - `device` is `rv32ik` or `rv64ik`, indicating the base 32/64-bit integer + ISA, with support for the Crypto extension. + + +- Alternativley, run these short commands: + + ```make + make -C tests/compliance compliance-run-spike + make -C tests/compliance compliance-run-sail-csim + make -C tests/compliance compliance-run-sail-ocaml + make -C tests/compliance compliance-run-all + ``` + + Which just wrap up the above long-form commands and run all of the + available compliance tests. + diff --git a/tests/compliance/riscv-compliance.patch b/tests/compliance/riscv-compliance.patch new file mode 100644 index 00000000..94c15e89 --- /dev/null +++ b/tests/compliance/riscv-compliance.patch @@ -0,0 +1,349 @@ +diff --git a/.gitignore b/.gitignore +index 4ff1094..974887a 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -1,5 +1,7 @@ + # Ignore editor backup files + *~ ++*.swp ++*.swo + # Ignore transients generated by the tests + /.cproject + /.project +diff --git a/riscv-target/sail-riscv-c/device/rv32ik/Makefile.include b/riscv-target/sail-riscv-c/device/rv32ik/Makefile.include +new file mode 100644 +index 0000000..4eb1564 +--- /dev/null ++++ b/riscv-target/sail-riscv-c/device/rv32ik/Makefile.include +@@ -0,0 +1,25 @@ ++TARGET_SIM ?= riscv_sim_RV32 ++TARGET_FLAGS ?= $(RISCV_TARGET_FLAGS) ++ ++ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),) ++ $(error Target simulator executable '$(TARGET_SIM)` not found) ++endif ++ ++RUN_TARGET=\ ++ $(TARGET_SIM) $(TARGET_FLAGS) \ ++ --test-signature=$(*).signature.output \ ++ $(<) 1>&2 2> $@ ++ ++RISCV_PREFIX ?= riscv32-unknown-elf- ++RISCV_GCC ?= $(RISCV_PREFIX)gcc ++RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump ++RISCV_GCC_OPTS ?= -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles $(RVTEST_DEFINES) ++ ++COMPILE_TARGET=\ ++ $$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \ ++ -I$(ROOTDIR)/riscv-test-env/ \ ++ -I$(ROOTDIR)/riscv-test-env/p/ \ ++ -I$(TARGETDIR)/$(RISCV_TARGET)/ \ ++ -T$(ROOTDIR)/riscv-test-env/p/link.ld $$(<) \ ++ -o $$(@); \ ++ $$(RISCV_OBJDUMP) -D $$(@) > $$(@).objdump +diff --git a/riscv-target/sail-riscv-ocaml/device/rv32ik/Makefile.include b/riscv-target/sail-riscv-ocaml/device/rv32ik/Makefile.include +new file mode 100644 +index 0000000..23f116e +--- /dev/null ++++ b/riscv-target/sail-riscv-ocaml/device/rv32ik/Makefile.include +@@ -0,0 +1,25 @@ ++TARGET_SIM ?= riscv_ocaml_sim_RV32 ++TARGET_FLAGS ?= $(RISCV_TARGET_FLAGS) ++ ++ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),) ++ $(error Target simulator executable '$(TARGET_SIM)` not found) ++endif ++ ++RUN_TARGET=\ ++ $(TARGET_SIM) $(TARGET_FLAGS) -isa=rv32 \ ++ -test-signature=$(*).signature.output \ ++ $(<) 2> $@ ++ ++RISCV_PREFIX ?= riscv32-unknown-elf- ++RISCV_GCC ?= $(RISCV_PREFIX)gcc ++RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump ++RISCV_GCC_OPTS ?= -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles $(RVTEST_DEFINES) ++ ++COMPILE_TARGET=\ ++ $$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \ ++ -I$(ROOTDIR)/riscv-test-env/ \ ++ -I$(ROOTDIR)/riscv-test-env/p/ \ ++ -I$(TARGETDIR)/$(RISCV_TARGET)/ \ ++ -T$(ROOTDIR)/riscv-test-env/p/link.ld $$(<) \ ++ -o $$(@); \ ++ $$(RISCV_OBJDUMP) -D $$(@) > $$(@).objdump +diff --git a/riscv-target/spike/device/rv32ik/Makefile.include b/riscv-target/spike/device/rv32ik/Makefile.include +new file mode 100644 +index 0000000..9a7a137 +--- /dev/null ++++ b/riscv-target/spike/device/rv32ik/Makefile.include +@@ -0,0 +1,29 @@ ++TARGET_SIM ?= spike ++TARGET_FLAGS ?= $(RISCV_TARGET_FLAGS) ++ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),) ++ $(error Target simulator executable '$(TARGET_SIM)` not found) ++endif ++ ++# TODO: rv32i -> rv32ik ++RUN_TARGET=\ ++ $(TARGET_SIM) $(TARGET_FLAGS) --isa=rv32i \ ++ +signature=$(*).signature.output \ ++ $< 2> $@; \ ++ cat $(*).signature.output | sed 's/.\{8\}/& /g' | \ ++ awk '{print $$4 " " $$3 " " $$2 " " $$1}' | sed 's/ /\n/g' > temp; \ ++ mv temp $(*).signature.output; ++ ++ ++RISCV_PREFIX ?= riscv32-unknown-elf- ++RISCV_GCC ?= $(RISCV_PREFIX)gcc ++RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump ++RISCV_GCC_OPTS ?= -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles ++ ++COMPILE_TARGET=\ ++ $$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \ ++ -I$(ROOTDIR)/riscv-test-env/ \ ++ -I$(ROOTDIR)/riscv-test-env/p/ \ ++ -I$(TARGETDIR)/$(RISCV_TARGET)/ \ ++ -T$(ROOTDIR)/riscv-test-env/p/link.ld $$(<) \ ++ -o $$@; \ ++ $$(RISCV_OBJDUMP) -D $$@ > $$@.objdump +diff --git a/riscv-test-env/riscv_test_macros.h b/riscv-test-env/riscv_test_macros.h +index 1a04591..e20542b 100644 +--- a/riscv-test-env/riscv_test_macros.h ++++ b/riscv-test-env/riscv_test_macros.h +@@ -212,6 +212,13 @@ + .fill 1, 8, -1; \ + .popsection + ++//Tests for a instructions with a single register operand ++#define TEST_R_OP(inst, destreg, reg1, correctval, val1, swreg, offset, testreg) \ ++ TEST_CASE(testreg, destreg, correctval, swreg, offset, \ ++ li reg1, MASK_XLEN(val1); \ ++ inst destreg, reg1; \ ++ ) ++ + //Tests for a instructions with register-register operand + #define TEST_RR_OP(inst, destreg, reg1, reg2, correctval, val1, val2, swreg, offset, testreg) \ + TEST_CASE(testreg, destreg, correctval, swreg, offset, \ +diff --git a/riscv-test-suite/rv32ik/.gitignore b/riscv-test-suite/rv32ik/.gitignore +new file mode 100644 +index 0000000..e69de29 +diff --git a/riscv-test-suite/rv32ik/Makefile b/riscv-test-suite/rv32ik/Makefile +new file mode 100644 +index 0000000..5684e5e +--- /dev/null ++++ b/riscv-test-suite/rv32ik/Makefile +@@ -0,0 +1,60 @@ ++#======================================================================= ++# Makefile for riscv-tests/isa ++#----------------------------------------------------------------------- ++ ++act_dir := . ++src_dir := $(act_dir)/src ++work_dir := $(ROOTDIR)/work ++work_dir_isa := $(work_dir)/$(RISCV_ISA) ++ ++include $(act_dir)/Makefrag ++ifneq ($(RISCV_TEST),) ++ target_tests = $(RISCV_TEST).elf ++endif ++ ++default: all ++ ++#-------------------------------------------------------------------- ++# Build rules ++#-------------------------------------------------------------------- ++ ++vpath %.S $(act_dir) ++ ++INCLUDE=$(TARGETDIR)/$(RISCV_TARGET)/device/$(RISCV_DEVICE)/Makefile.include ++ifeq ($(wildcard $(INCLUDE)),) ++ $(error Cannot find '$(INCLUDE)`. Check that RISCV_TARGET and RISCV_DEVICE are set correctly.) ++endif ++-include $(INCLUDE) ++ ++#------------------------------------------------------------ ++# Build and run assembly tests ++ ++%.log: %.elf ++ $(V) echo "Execute $(@)" ++ $(V) $(RUN_TARGET) ++ ++ ++define compile_template ++ ++$(work_dir_isa)/%.elf: $(src_dir)/%.S ++ $(V) echo "Compile $$(@)" ++ @mkdir -p $$(@D) ++ $(V) $(COMPILE_TARGET) ++ ++.PRECIOUS: $(work_dir_isa)/%.elf ++ ++endef ++ ++# TODO - change rv32i -> rv32ik ++$(eval $(call compile_template,-march=rv32i -mabi=ilp32)) ++ ++target_elf = $(foreach e,$(target_tests),$(work_dir_isa)/$(e)) ++target_log = $(patsubst %.elf,%.log,$(target_elf)) ++ ++run: $(target_log) ++ ++#------------------------------------------------------------ ++# Clean up ++ ++clean: ++ rm -rf $(work_dir) +diff --git a/riscv-test-suite/rv32ik/Makefrag b/riscv-test-suite/rv32ik/Makefrag +new file mode 100644 +index 0000000..97177b5 +--- /dev/null ++++ b/riscv-test-suite/rv32ik/Makefrag +@@ -0,0 +1,35 @@ ++# RISC-V Compliance Test RV32IK Makefrag ++# ++# Copyright (c) 2017, Codasip Ltd. ++# All rights reserved. ++# ++# Redistribution and use in source and binary forms, with or without ++# modification, are permitted provided that the following conditions are met: ++# * Redistributions of source code must retain the above copyright ++# notice, this list of conditions and the following disclaimer. ++# * Redistributions in binary form must reproduce the above copyright ++# notice, this list of conditions and the following disclaimer in the ++# documentation and/or other materials provided with the distribution. ++# * Neither the name of the Codasip Ltd. nor the ++# names of its contributors may be used to endorse or promote products ++# derived from this software without specific prior written permission. ++# ++# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS ++# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ++# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Codasip Ltd. BE LIABLE FOR ANY ++# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++# ++# Description: Makefrag for RV32I compliance tests ++ ++rv32ik_tests_notrap = \ ++ K-SHA2SUM0-01 ++ ++rv32ik_tests = $(addsuffix .elf, $(rv32ik_tests_notrap)) ++ ++target_tests += $(rv32ik_tests) +diff --git a/riscv-test-suite/rv32ik/references/K-SHA2SUM0-01.reference_output b/riscv-test-suite/rv32ik/references/K-SHA2SUM0-01.reference_output +new file mode 100644 +index 0000000..c98422d +--- /dev/null ++++ b/riscv-test-suite/rv32ik/references/K-SHA2SUM0-01.reference_output +@@ -0,0 +1,8 @@ ++00000000 ++80100800 ++00201001 ++00402002 ++00000000 ++80100800 ++00201001 ++00402002 +diff --git a/riscv-test-suite/rv32ik/src/K-SHA2SUM0-01.S b/riscv-test-suite/rv32ik/src/K-SHA2SUM0-01.S +new file mode 100644 +index 0000000..cfbddd2 +--- /dev/null ++++ b/riscv-test-suite/rv32ik/src/K-SHA2SUM0-01.S +@@ -0,0 +1,92 @@ ++# RISC-V Compliance Test SHA2SUM0-01 ++# ++# Redistribution and use in source and binary forms, with or without ++# modification, are permitted provided that the following conditions are met: ++# * Redistributions of source code must retain the above copyright ++# notice, this list of conditions and the following disclaimer. ++# * Redistributions in binary form must reproduce the above copyright ++# notice, this list of conditions and the following disclaimer in the ++# documentation and/or other materials provided with the distribution. ++# * Neither the name of the Imperas Software Ltd. nor the ++# names of its contributors may be used to endorse or promote products ++# derived from this software without specific prior written permission. ++# ++# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS ++# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ++# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Imperas Software Ltd. BE LIABLE FOR ANY ++# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++# ++# Specification: RV32IK Base Integer Instruction Set, Version 2.1 ++# Description: Testing instruction 'SHA2SUM0'. ++ ++#include "riscv_test_macros.h" ++#include "compliance_test.h" ++#include "compliance_io.h" ++ ++RV_COMPLIANCE_RV32M ++ ++RV_COMPLIANCE_CODE_BEGIN ++ ++ ++ RVTEST_IO_INIT ++ RVTEST_IO_ASSERT_GPR_EQ(x31, x0, 0x00000000) ++ RVTEST_IO_WRITE_STR(x31, "Test Begin\n") ++ ++ # --------------------------------------------------------------------- ++ ++ RVTEST_IO_WRITE_STR(x31, "# Test number 1\n") ++ ++ ++ # address for test results ++ la x5, test_1_res ++ ++ TEST_R_OP(sha256sum0, x0, x31, 0x0, 0x01, x5, 0, x6) # Testcase 0 ++ TEST_R_OP(sha256sum0, x1, x30, 0x0, 0x02, x5, 4, x6) # Testcase 1 ++ TEST_R_OP(sha256sum0, x2, x29, 0x0, 0x04, x5, 8, x6) # Testcase 2 ++ TEST_R_OP(sha256sum0, x3, x28, 0x0, 0x08, x5,12, x6) # Testcase 3 ++ TEST_R_OP(sha256sum0, x4, x27, 0x0, 0x10, x5,16, x6) # Testcase 4 ++ ++ # --------------------------------------------------------------------- ++ ++ RVTEST_IO_WRITE_STR(x31, "# Test number 2\n") ++ ++ ++ # address for test results ++ la x5, test_2_res ++ ++ TEST_R_OP(sha256sum0, x0, x0 , 0x0, 0x01, x5, 0, x6) # Testcase 0 ++ TEST_R_OP(sha256sum0, x1, x1 , 0x0, 0x02, x5, 4, x6) # Testcase 1 ++ TEST_R_OP(sha256sum0, x2, x2 , 0x0, 0x04, x5, 8, x6) # Testcase 2 ++ TEST_R_OP(sha256sum0, x3, x3 , 0x0, 0x08, x5,12, x6) # Testcase 3 ++ TEST_R_OP(sha256sum0, x4, x4 , 0x0, 0x10, x5,16, x6) # Testcase 4 ++ ++ # --------------------------------------------------------------------- ++ ++ RVTEST_IO_WRITE_STR(x31, "Test End\n") ++ ++ # --------------------------------------------------------------------- ++ ++ RV_COMPLIANCE_HALT ++ ++RV_COMPLIANCE_CODE_END ++ ++# Input data section. ++ .data ++ ++# Output data section. ++RV_COMPLIANCE_DATA_BEGIN ++ ++test_1_res: ++ .fill 4, 4, -1 ++test_2_res: ++ .fill 4, 4, -1 ++ ++RV_COMPLIANCE_DATA_END ++ ++