blob: 8fdb0e549bf35735ff92f59bd9844bdcec14851c [file] [log] [blame]
From 12485c998481c4414e157a7b6d475c2c118fce77 Mon Sep 17 00:00:00 2001
From: Greg Chadwick <gac@lowrisc.org>
Date: Wed, 15 Apr 2020 15:44:54 +0100
Subject: [PATCH 2/5] Add OpenTitan target
diff --git a/Makefile b/Makefile
index 25557c1..a6fd315 100644
--- a/Makefile
+++ b/Makefile
@@ -50,6 +50,11 @@ else
ifeq ($(RISCV_TARGET),riscvOVPsim)
JOBS ?= -j8 --max-load=4
endif
+ ifeq ($(RISCV_TARGET),opentitan)
+ ifeq ($(OT_TARGET),sim_verilator)
+ JOBS ?= -j4
+ endif
+ endif
endif
default: $(DEFAULT_TARGET)
@@ -90,4 +95,3 @@ help:
@echo "RISCV_ISA='$(RISCV_ISA_OPT)'"
@echo "RISCV_TEST='I-ADD-01'"
@echo "make all_variant // all combinations"
-
diff --git a/riscv-target/opentitan/README.md b/riscv-target/opentitan/README.md
new file mode 100644
index 0000000..353a9b3
--- /dev/null
+++ b/riscv-target/opentitan/README.md
@@ -0,0 +1,152 @@
+
+# Overview
+The RISC-V compliance test can be run on either OpenTitan FPGA or Verilator.
+OpenTitan is an open source project to build transparent, high-quality reference
+designs for silicon root of trust chips. Please see the [OpenTitan
+website](https://opentitan.org) for more details.
+
+To run on Verilator, set the variables below
+
+```console
+$ export RISCV_TARGET=opentitan
+$ export RISCV_DEVICE=rv32imc
+$ export OT_TARGET=sim_verilator
+```
+
+To run on FPGA, set the variables below. The `OT_FPGA_UART` variable must be
+set to wherever a valid device is connected.
+
+```console
+$ export RISCV_TARGET=opentitan
+$ export RISCV_DEVICE=rv32imc
+$ export OT_TARGET=fpga_nexysvideo
+$ export OT_FPGA_UART=/dev/tty*
+```
+
+By default, the test assumes there exists a valid Verilator build at
+`${REPO_TOP}/build/lowrisc_systems_top_earlgrey_verilator_0.1/sim-verilator/Vtop_earlgrey_verilator`.
+If your Verilator build is at a different location, please set that as well when
+running with Verilator.
+
+```console
+$ export TARGET_SIM=${PATH_TO_VERILATOR_BUILD}
+```
+
+When running against FPGA, the test assumes the FPGA is already programmed and
+ready to go with spiflash available at `$BIN_DIR/sw/host/spiflash/spiflash`.
+To quickly get started with a verilator binary or FPGA bitfile, please see the
+[OpenTitan quick start guide](https://docs.opentitan.org/doc/ug/quickstart/).
+
+Finally the support software must be built, including the test_rom when using
+the verilator target.
+
+```console
+$ cd $REPO_TOP
+$ ./meson_init.sh
+$ ninja -C ./build-out all
+```
+
+Now, run the tests from the riscv_compliance directory. The following output
+will be seen (software build steps are truncated). The example below uses
+Verilator as an example, but the FPGA output is nearly identical.
+
+```console
+$ cd $RISCV_COMPLIANCE_REPO_BASE
+$ make RISCV_ISA=rv32i
+
+... verbose test output ...
+
+Compare to reference files ...
+
+Check I-ADD-01 ... OK
+Check I-ADDI-01 ... OK
+Check I-AND-01 ... OK
+Check I-ANDI-01 ... OK
+Check I-AUIPC-01 ... OK
+Check I-BEQ-01 ... OK
+Check I-BGE-01 ... OK
+Check I-BGEU-01 ... OK
+Check I-BLT-01 ... OK
+Check I-BLTU-01 ... OK
+Check I-BNE-01 ... OK
+Check I-DELAY_SLOTS-01 ... OK
+Check I-EBREAK-01 ... OK
+Check I-ECALL-01 ... OK
+Check I-ENDIANESS-01 ... OK
+Check I-IO-01 ... OK
+Check I-JAL-01 ... OK
+Check I-JALR-01 ... OK
+Check I-LB-01 ... OK
+Check I-LBU-01 ... OK
+Check I-LH-01 ... OK
+Check I-LHU-01 ... OK
+Check I-LUI-01 ... OK
+Check I-LW-01 ... OK
+Check I-MISALIGN_JMP-01 ... IGNORE
+Check I-MISALIGN_LDST-01 ... IGNORE
+Check I-NOP-01 ... OK
+Check I-OR-01 ... OK
+Check I-ORI-01 ... OK
+Check I-RF_size-01 ... OK
+Check I-RF_width-01 ... OK
+Check I-RF_x0-01 ... OK
+Check I-SB-01 ... OK
+Check I-SH-01 ... OK
+Check I-SLL-01 ... OK
+Check I-SLLI-01 ... OK
+Check I-SLT-01 ... OK
+Check I-SLTI-01 ... OK
+Check I-SLTIU-01 ... OK
+Check I-SLTU-01 ... OK
+Check I-SRA-01 ... OK
+Check I-SRAI-01 ... OK
+Check I-SRL-01 ... OK
+Check I-SRLI-01 ... OK
+Check I-SUB-01 ... OK
+Check I-SW-01 ... OK
+Check I-XOR-01 ... OK
+Check I-XORI-01 ... OK
+--------------------------------
+OK: 48/48
+```
+
+There are several test suites that can be run `rv32i`, `rv32im`, `rv32imc` and
+`rv32Zicsr`. Change the `RISCV_ISA` argument passed to `make` to choose between
+them.
+
+## Changing targets
+When switching between targets (i.e. between FPGA and verilator) the `work`
+directory in the `riscv_compliance` tree must be remove to force a software
+rebuild.
+
+```console
+$ cd $RISCV_COMPLIANCE_REPO_BASE
+$ rm -rf ./work
+```
+
+## Parallel runs
+When running against the `sim_verilator` target parallel make jobs are used (via
+passing `-j4` to make internally). Parallel runs can be disabled by passing
+`PARALLEL=0` to the `make` command or the `-j` used can be altered with the
+`JOBS` argument.
+
+Disable parallel runs:
+```console
+$ make RISCV_ISA=rv32i PARALLEL=0
+```
+
+Use a different `-j` parameter:
+```console
+$ make RISCV_ISA=rv32i JOBS=-j8
+```
+
+## Removed/Broken Tests
+A small number of tests are not run for OpenTitan riscv_compliance as they fail
+due to flaws in the compliance test suite rather than Ibex/OpenTitan itself (see
+https://github.com/lowRISC/ibex/issues/100). The I-FENCE.I-01 test attempts to
+write instruction memory which fails in the OT system as this writes to flash
+which can't be done.
+
+* I-MISALIGN_JMP-01
+* I-MISALIGN_LDST-01
+* I-FENCE.I-01
diff --git a/riscv-target/opentitan/compliance_io.h b/riscv-target/opentitan/compliance_io.h
new file mode 100644
index 0000000..d5d88d4
--- /dev/null
+++ b/riscv-target/opentitan/compliance_io.h
@@ -0,0 +1,22 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// RISC-V Compliance IO Test Header File
+
+
+#ifndef _COMPLIANCE_IO_H
+#define _COMPLIANCE_IO_H
+
+//-----------------------------------------------------------------------
+// RV IO Macros (Non functional)
+//-----------------------------------------------------------------------
+
+#define RVTEST_IO_INIT
+#define RVTEST_IO_WRITE_STR(_SP, _STR)
+#define RVTEST_IO_CHECK()
+#define RVTEST_IO_ASSERT_GPR_EQ(_SP, _R, _I)
+#define RVTEST_IO_ASSERT_SFPR_EQ(_F, _R, _I)
+#define RVTEST_IO_ASSERT_DFPR_EQ(_D, _R, _I)
+
+#endif // _COMPLIANCE_IO_H
diff --git a/riscv-target/opentitan/compliance_test.h b/riscv-target/opentitan/compliance_test.h
new file mode 100644
index 0000000..6a889cf
--- /dev/null
+++ b/riscv-target/opentitan/compliance_test.h
@@ -0,0 +1,35 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// RISC-V Compliance Test Header File
+
+#ifndef _COMPLIANCE_TEST_H
+#define _COMPLIANCE_TEST_H
+
+#include "riscv_test.h"
+
+//-----------------------------------------------------------------------
+// RV Compliance Macros
+//-----------------------------------------------------------------------
+#define RV_COMPLIANCE_HALT \
+ j end_rvc_test; \
+
+#define RV_COMPLIANCE_RV32M \
+ RVTEST_RV32M \
+
+
+#define RV_COMPLIANCE_CODE_BEGIN \
+ RVTEST_CODE_BEGIN \
+
+#define RV_COMPLIANCE_CODE_END \
+ RVTEST_CODE_END \
+
+#define RV_COMPLIANCE_DATA_BEGIN \
+ .section .data; \
+ RVTEST_DATA_BEGIN \
+
+#define RV_COMPLIANCE_DATA_END \
+ RVTEST_DATA_END \
+
+#endif
diff --git a/riscv-target/opentitan/device/rv32imc/Makefile.include b/riscv-target/opentitan/device/rv32imc/Makefile.include
new file mode 100644
index 0000000..b71105c
--- /dev/null
+++ b/riscv-target/opentitan/device/rv32imc/Makefile.include
@@ -0,0 +1,75 @@
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+
+OPENTITAN = $(ROOTDIR)/riscv-target/$(RISCV_TARGET)/device/rv32imc
+OT_ROOT ?= $(ROOTDIR)/../../../
+OT_SW = $(OT_ROOT)/sw/device
+OT_BIN ?= $(OT_ROOT)/build-bin
+OT_TOOLS ?= /tools/riscv/bin
+OT_FPGA_UART ?=
+OT_TARGET ?= fpga_nexysvideo
+LDSCRIPT = $(OT_ROOT)/sw/device/exts/common/flash_link.ld
+DEFINES = $(CARG) -DPRIV_MISA_S=0 -DPRIV_MISA_U=0 -DRVTEST_ENTRY=_rvc_start -DTRAPALIGN=8
+TARGET_SIM ?= $(OT_ROOT)/build/lowrisc_systems_top_earlgrey_verilator_0.1/sim-verilator/Vtop_earlgrey_verilator
+
+COMPLIANCE_LIB_EXPORT = sw/device/riscv_compliance_support/riscv_compliance_support_export_$(OT_TARGET)
+COMPLIANCE_LIB = ot_riscv_compliance_support_$(OT_TARGET)
+
+# The run target recipe does the following things:
+# Invoke pytest to run the test
+# Parse the resulting log for the output signatures
+# Convert all signatures to lower case since the reference is in all lower case
+ifeq ($(OT_TARGET),sim_verilator)
+ MAKEARG = SIM=1
+ CARG = -DSIMULATION=1
+ RUN_TARGET = \
+ $(TARGET_SIM) \
+ --meminit="rom,$(OT_BIN)/sw/device/lib/testing/test_rom/test_rom_sim_verilator.elf" \
+ --meminit="flash,$(<)" \
+ +UARTDPI_LOG_uart0="$(*).uart.log" > $@ 2>&1 \
+ && sed -e 's/^/[UART $(shell basename $(*))] /' "$(*).uart.log" $(REDIR) \
+ && grep -o 'SIG: [a-zA-Z0-9_]*' "$(*).uart.log" \
+ | sed 's/SIG: //' > $(*).signature.output
+else ifeq ($(OT_TARGET),fpga_nexysvideo)
+ MAKEARG =
+ CARG =
+ RUN_TARGET = \
+ ( test -e "$(OT_FPGA_UART)" || ( echo "UART device '$(OT_FPGA_UART)' not available. Set OT_FPGA_UART." >&2 && exit 1 ) ) \
+ && echo "Writing '$(<).bin' to device." \
+ && $(OT_BIN)/sw/host/spiflash/spiflash --input="$(<).bin" \
+ && stty -F "$(OT_FPGA_UART)" speed 115200 cs8 -cstopb -parenb \
+ && grep -o 'SIG: [a-zA-Z0-9_]*' "$(OT_FPGA_UART)" \
+ | sed 's/SIG: //' > $(*).signature.output
+else
+ $(error Unsupported target $(OT_TARGET))
+endif
+
+RISCV_PREFIX ?= ${OT_TOOLS}/riscv32-unknown-elf-
+RISCV_GCC ?= ${OT_TOOLS}/riscv32-unknown-elf-gcc
+RISCV_OBJDUMP ?= ${OT_TOOLS}/riscv32-unknown-elf-objdump
+RISCV_OBJCOPY ?= ${OT_TOOLS}/riscv32-unknown-elf-objcopy
+RISCV_NM ?= ${OT_TOOLS}/riscv32-unknown-elf-nm
+RISCV_READELF ?= ${OT_TOOLS}/riscv32-unknown-elf-readelf
+RISCV_GCC_OPTS ?= -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles -fno-builtin -g -Wl,--no-relax
+
+COMPILE_TARGET += \
+ $$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \
+ -I$(ROOTDIR)/riscv-test-env/ \
+ -I$(ROOTDIR)/riscv-test-env/p/ \
+ -I$(OT_ROOT) \
+ -I$(TARGETDIR)/$(RISCV_TARGET)/ \
+ -I$(TARGETDIR)/$(RISCV_TARGET)/ \
+ $(DEFINES) \
+ -L$(OT_ROOT) -T$(LDSCRIPT) $$< \
+ $(OPENTITAN)/main.c \
+ $(OPENTITAN)/run_rvc_test.S \
+ $(OT_ROOT)/sw/device/exts/common/ibex_interrupt_vectors.S \
+ $(OT_ROOT)/sw/device/exts/common/flash_crt.S \
+ -L$(OT_BIN)/sw/device/riscv_compliance_support \
+ -l$(COMPLIANCE_LIB) \
+ -o $$(@); \
+ $$(RISCV_OBJDUMP) -SD $$(@) > $$(@).objdump; \
+ $$(RISCV_READELF) -a $$(@) > $$(@).readelf; \
+ $$(RISCV_NM) $$(@) > $$(@).nm; \
+ $$(RISCV_OBJCOPY) -O binary $$(@) $$(@).bin;
diff --git a/riscv-target/opentitan/device/rv32imc/isa.yaml b/riscv-target/opentitan/device/rv32imc/isa.yaml
new file mode 100644
index 0000000..c526fec
--- /dev/null
+++ b/riscv-target/opentitan/device/rv32imc/isa.yaml
@@ -0,0 +1,49 @@
+## Copyright lowRISC contributors.
+## Licensed under the Apache License, Version 2.0, see LICENSE for details.
+## SPDX-License-Identifier: Apache-2.0
+
+Device: rv32imc
+Vendor: opentitan
+
+ISA: RV32IMC
+misa:
+ implemented: True
+ MXL:
+ range:
+ rangelist: [[1]]
+ mode: Unchanged
+ Extensions:
+ bitmask:
+ mask: 0x0
+ default: 0x1104
+hw_data_misaligned_support: True
+mtvec:
+ MODE:
+ range:
+ rangelist: [[1]]
+ BASE:
+ range:
+ rangelist: [[0x20000020]]
+
+mstatus:
+ MPP:
+ range:
+ rangelist: [[3]]
+
+User_Spec_Version: "2.3"
+Privilege_Spec_Version: "1.11"
+
+mvendorid:
+ implemented: false
+marchid:
+ implemented: false
+mimpid:
+ implemented: false
+mhartid: 0
+
+mcycle:
+ is_hardwired: true
+ implemented: true
+minstret:
+ is_hardwired: true
+ implemented: true
diff --git a/riscv-target/opentitan/device/rv32imc/main.c b/riscv-target/opentitan/device/rv32imc/main.c
new file mode 100644
index 0000000..8d67e4e
--- /dev/null
+++ b/riscv-target/opentitan/device/rv32imc/main.c
@@ -0,0 +1,13 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// NOTE: This is the only header from OpenTitan that can be imported here. Any
+// OpenTitan-specific work should be done in support.c, instead.
+// Doing this avoids having to create patches for this file any time
+// requirements for the wrapper change.
+#include "sw/device/riscv_compliance_support/support.h"
+
+int main(int argc, char **argv) {
+ return opentitan_compliance_main(argc, argv);
+}
diff --git a/riscv-target/opentitan/device/rv32imc/platform.yaml b/riscv-target/opentitan/device/rv32imc/platform.yaml
new file mode 100644
index 0000000..7d547d9
--- /dev/null
+++ b/riscv-target/opentitan/device/rv32imc/platform.yaml
@@ -0,0 +1,10 @@
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+
+mtime:
+ implemented: False
+nmi:
+ address: 0x800000FC # trap vec (mtvec base) + 0x7C
+reset:
+ address: 0x80000080 # boot address + 0x80
diff --git a/riscv-target/opentitan/device/rv32imc/run_rvc_test.S b/riscv-target/opentitan/device/rv32imc/run_rvc_test.S
new file mode 100644
index 0000000..1b1b5c7
--- /dev/null
+++ b/riscv-target/opentitan/device/rv32imc/run_rvc_test.S
@@ -0,0 +1,85 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// Allocate space in .bss for saving architectural state before jumping into the
+// test
+ .lcomm arch_state_store, 4 * 17 //(ra, sp, gp, tp, s0-s11, mtvec)
+
+ .section .text
+
+run_rvc_test:
+ .globl run_rvc_test
+
+ // Save the architectural state. There is no need to save caller preserved
+ // registers as C calling run_rvc_test will expect them to be clobbered anyway
+ // and act appropriately. RA is the exception as we need to know where to jump
+ // back to after the test is complete. mtvec is saved as the compliance test
+ // environment alters it, other CSRs may also be changed but no adverse
+ // effects have yet been observed from this.
+ la t0, arch_state_store
+
+ sw ra, 0(t0)
+ sw sp, 4(t0)
+ sw gp, 8(t0)
+ sw tp, 12(t0)
+ sw s0, 16(t0)
+ sw s1, 20(t0)
+ sw s2, 24(t0)
+ sw s3, 28(t0)
+ sw s4, 32(t0)
+ sw s5, 36(t0)
+ sw s6, 40(t0)
+ sw s7, 44(t0)
+ sw s8, 48(t0)
+ sw s9, 52(t0)
+ sw s10, 56(t0)
+ sw s11, 60(t0)
+
+ csrr t1, mtvec
+ sw t1, 64(t0)
+
+// jump to compliance test
+ j _rvc_start
+
+end_rvc_test:
+ .globl end_rvc_test
+
+ // restore architectural state
+ la t0, arch_state_store
+
+ lw ra, 0(t0)
+ lw sp, 4(t0)
+ lw gp, 8(t0)
+ lw tp, 12(t0)
+ lw s0, 16(t0)
+ lw s1, 20(t0)
+ lw s2, 24(t0)
+ lw s3, 28(t0)
+ lw s4, 32(t0)
+ lw s5, 36(t0)
+ lw s6, 40(t0)
+ lw s7, 44(t0)
+ lw s8, 48(t0)
+ lw s9, 52(t0)
+ lw s10, 56(t0)
+ lw s11, 60(t0)
+
+ lw t1, 64(t0)
+ csrw mtvec, t1
+
+ jr ra
+
+// riscv-compliance loads its own mtvec that will jump to mtvec_handler if the
+// symbol exists
+mtvec_handler:
+ .globl mtvec_handler
+
+ // restore gp/sp so handler from OT library can work
+ la t0, arch_state_store
+
+ lw sp, 4(t0)
+ lw gp, 8(t0)
+
+ // jump to the handler from the OT library
+ j crt_interrupt_vector