Skip to content

Integrate riscv-arch-test #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jan 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
build/DOOM1.WAD*
shareware_doom_iwad.zip*
build/rv32emu
build/arch-test
*.o
*.o.d
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "riscv-arch-test"]
path = riscv-arch-test
url = https://github.com/riscv-non-isa/riscv-arch-test
15 changes: 15 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,21 @@ check: $(BIN)
(cd $(OUT); ../$(BIN) hello.elf)
(cd $(OUT); ../$(BIN) puzzle.elf)

ARCH_TEST_DIR ?= ./riscv-arch-test
export RISCV_TARGET = arch-test-target
export RISCV_PREFIX ?= riscv-none-embed-
export TARGETDIR = $(shell pwd)
export XLEN = 32
export JOBS ?= -j
export WORK = $(TARGETDIR)/build/arch-test

$(ARCH_TEST__DIR):
git submodule update --init

arch-test: $(BIN) $(ARCH_TEST__DIR)
$(Q)$(MAKE) --quiet -C $(ARCH_TEST_DIR) clean
$(Q)$(MAKE) --quiet -C $(ARCH_TEST_DIR)

demo: $(BIN) $(OUT)/DOOM1.WAD
(cd $(OUT); ../$(BIN) doom.elf)

Expand Down
51 changes: 51 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,57 @@ make demo
The build script will then download data file for Doom automatically. SDL2 based window
should appear when Doom is loaded and executed.

## riscv-arch-test

The RISC-V Architectural Tests, [riscv-arch-test](https://github.com/riscv-non-isa/riscv-arch-test), is the basic set of tests that can ensure the risc-v model's behavior that matches RISC-V specifications while implementing specific software.(not a **substitute for rigorous design verification**)

There are **reference signatures** that generated by the formal RISC-V model [RISC-V SAIL](https://github.com/riscv/sail-riscv) and the Executable and Linkable Format(`ELF`) files. The `ELF` files such as `cadd-01.elf` that contain several testing instructions, data, and **signatures**. The **test signatures** are the specific data locations that need to be written by testing model(this emulator) during the test. Once the test is executed, the **test signatures** will be written and compared to the **reference signature**. The test will pass if both signatures exactly match.

[riscv-arch-test](https://github.com/riscv-non-isa/riscv-arch-test) is integrated with submodule, and the setup was done.Once the submodule `riscv-arch-test` is pulled, run all the available riscv-arch-test via command:
```shell
make arch-test
```

* To run the tests for specific extension, set the environmental variable `RISCV_DEVICE` to one of `I`,`M`,`C`,`Zifencei`,`privilege`.
```shell
make arch-test RISCV_DEVICE=I
```
* To run a specific test case,set both `RISCV_DEVICE` and `RISCV_TEST`.For example:
```shell
make arch-test RISCV_DEVICE=M RISCV_TEST=div-01
```
The details about the setup environment variables can be found in the [RISC-V Architectural Testing Framework](https://github.com/riscv-non-isa/riscv-arch-test/blob/master/doc/README.adoc), **5.1 Setup environment variables**.

Current progress of this emulator in riscv-arch-test(RV32):
* Passed Tests
- `I`: Base Integer Instruction Set
- `M`: Standard Extension for Integer Multiplication and Division
- `Zifencei`: Instruction-Fetch Fence
* Failed Tests
- `C`: Standard Extension for Compressed Instruction
+ `cebreak`
- `privilege`: RISCV Privileged Specification
+ 2 system calls
* `ebreak`
* `ecall`
+ 5 misaligned CB-type instructions
* `misalign-beq`
* `misalign-bge`
* `misalign-bgeu`
* `misalign-blt`
* `misalign-bltu`
+ 1 misaligned CL-type instructions
* `misalign-lw`
+ 1 misaligned CS-type instructions
* `misalign-sw`
* Unsupported tests
- `F` Standard Extension for Single-Precision Floating-Point

Detail in riscv-arch-test:
* [riscv-arch-test repository](https://github.com/riscv-non-isa/riscv-arch-test)
* [RISC-V Architectural Testing Framework](https://github.com/riscv-non-isa/riscv-arch-test/blob/master/doc/README.adoc)
* [RISC-V Architecture Test Format Specification](https://github.com/riscv-non-isa/riscv-arch-test/blob/master/spec/TestFormatSpec.adoc)

## Customization

`rv32emu` is configurable, and you can modify `Makefile` to fit your expectations:
Expand Down
22 changes: 22 additions & 0 deletions arch-test-target/device/rv32i_m/C/Makefile.include
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
RUN_TARGET= $(TARGETDIR)/build/rv32emu $(<) \
$(RISCV_TARGET_FLAGS) \
--arch-test $(*).signature.output \
1>$(@) 2>&1

RISCV_GCC ?= $(RISCV_PREFIX)gcc
RISCV_GCC_OPTS ?= \
-march=rv32gc \
-mabi=ilp32 \
-static \
-mcmodel=medany \
-fvisibility=hidden \
$(RVTEST_DEFINES) \
-nostdlib \
-nostartfiles

COMPILE_TARGET = \
$$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \
-I$(ROOTDIR)/riscv-test-suite/env/ \
-I$(TARGETDIR)/$(RISCV_TARGET)/ \
-T$(TARGETDIR)/$(RISCV_TARGET)/link.ld \
$$(<) -o $$(@);
22 changes: 22 additions & 0 deletions arch-test-target/device/rv32i_m/I/Makefile.include
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
RUN_TARGET= $(TARGETDIR)/build/rv32emu $(<) \
$(RISCV_TARGET_FLAGS) \
--arch-test $(*).signature.output \
1>$(@) 2>&1

RISCV_GCC ?= $(RISCV_PREFIX)gcc
RISCV_GCC_OPTS ?= \
-march=rv32g \
-mabi=ilp32 \
-static \
-mcmodel=medany \
-fvisibility=hidden \
$(RVTEST_DEFINES) \
-nostdlib \
-nostartfiles

COMPILE_TARGET = \
$$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \
-I$(ROOTDIR)/riscv-test-suite/env/ \
-I$(TARGETDIR)/$(RISCV_TARGET)/ \
-T$(TARGETDIR)/$(RISCV_TARGET)/link.ld \
$$(<) -o $$(@);
22 changes: 22 additions & 0 deletions arch-test-target/device/rv32i_m/M/Makefile.include
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
RUN_TARGET= $(TARGETDIR)/build/rv32emu $(<) \
$(RISCV_TARGET_FLAGS) \
--arch-test $(*).signature.output \
1>$(@) 2>&1

RISCV_GCC ?= $(RISCV_PREFIX)gcc
RISCV_GCC_OPTS ?= \
-march=rv32g \
-mabi=ilp32 \
-static \
-mcmodel=medany \
-fvisibility=hidden \
$(RVTEST_DEFINES) \
-nostdlib \
-nostartfiles

COMPILE_TARGET = \
$$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \
-I$(ROOTDIR)/riscv-test-suite/env/ \
-I$(TARGETDIR)/$(RISCV_TARGET)/ \
-T$(TARGETDIR)/$(RISCV_TARGET)/link.ld \
$$(<) -o $$(@);
22 changes: 22 additions & 0 deletions arch-test-target/device/rv32i_m/Zifencei/Makefile.include
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
RUN_TARGET= $(TARGETDIR)/build/rv32emu $(<) \
$(RISCV_TARGET_FLAGS) \
--arch-test $(*).signature.output \
1>$(@) 2>&1

RISCV_GCC ?= $(RISCV_PREFIX)gcc
RISCV_GCC_OPTS ?= \
-march=rv32g \
-mabi=ilp32 \
-static \
-mcmodel=medany \
-fvisibility=hidden \
$(RVTEST_DEFINES) \
-nostdlib \
-nostartfiles

COMPILE_TARGET = \
$$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \
-I$(ROOTDIR)/riscv-test-suite/env/ \
-I$(TARGETDIR)/$(RISCV_TARGET)/ \
-T$(TARGETDIR)/$(RISCV_TARGET)/link.ld \
$$(<) -o $$(@);
22 changes: 22 additions & 0 deletions arch-test-target/device/rv32i_m/privilege/Makefile.include
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
RUN_TARGET= $(TARGETDIR)/build/rv32emu $(<) \
$(RISCV_TARGET_FLAGS) \
--arch-test $(*).signature.output \
1>$(@) 2>&1

RISCV_GCC ?= $(RISCV_PREFIX)gcc
RISCV_GCC_OPTS ?= \
-march=rv32gc \
-mabi=ilp32 \
-static \
-mcmodel=medany \
-fvisibility=hidden \
$(RVTEST_DEFINES) \
-nostdlib \
-nostartfiles

COMPILE_TARGET = \
$$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \
-I$(ROOTDIR)/riscv-test-suite/env/ \
-I$(TARGETDIR)/$(RISCV_TARGET)/ \
-T$(TARGETDIR)/$(RISCV_TARGET)/link.ld \
$$(<) -o $$(@);
15 changes: 15 additions & 0 deletions arch-test-target/link.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
OUTPUT_ARCH( "riscv" )
ENTRY(rvtest_entry_point)

SECTIONS
{
. = 0x80000000;
.text.init : { *(.text.init) }
. = ALIGN(0x1000);
.text : { *(.text) }
. = ALIGN(0x1000);
.data : { *(.data) }
.data.string : { *(.data.string)}
.bss : { *(.bss) }
_end = .;
}
26 changes: 26 additions & 0 deletions arch-test-target/model_test.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

#define RVMODEL_HALT \
add a7, x0, 93; \
add a0, x0, 0; \
ecall

#define RVMODEL_BOOT

#define RVTEST_RV32M

#define RVMODEL_DATA_BEGIN \
.align 4; .global begin_signature; begin_signature:

#define RVMODEL_DATA_END \
.align 4; .global end_signature; end_signature:

#define RVMODEL_IO_INIT
#define RVMODEL_IO_WRITE_STR(_SP, _STR)
#define RVMODEL_IO_CHECK()
#define RVMODEL_IO_ASSERT_GPR_EQ(_SP, _R, _I)
#define RVMODEL_IO_ASSERT_SFPR_EQ(_F, _R, _I)
#define RVMODEL_IO_ASSERT_DFPR_EQ(_D, _R, _I)
#define RVMODEL_SET_MSW_INT
#define RVMODEL_CLEAR_MSW_INT
#define RVMODEL_CLEAR_MTIMER_INT
#define RVMODEL_CLEAR_MEXT_INT
32 changes: 32 additions & 0 deletions elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,26 @@ enum {
STT_TLS = 6,
};

enum {
SHT_NULL = 0,
SHT_PROGBITS = 1,
SHT_SYMTAB = 2,
SHT_STRTAB = 3,
SHT_RELA = 4,
SHT_HASH = 5,
SHT_DYNAMIC = 6,
SHT_NOTE = 7,
SHT_NOBITS = 8,
SHT_REL = 9,
SHT_SHLIB = 10,
SHT_DYNSYM = 11,
SHT_NUM = 12,
SHT_LOPROC = 0x70000000,
SHT_HIPROC = 0x7fffffff,
SHT_LOUSER = 0x80000000,
SHT_HIUSER = 0xffffffff
};

#define ELF_ST_TYPE(x) (((unsigned int) x) & 0xf)

struct Elf32_Ehdr {
Expand Down Expand Up @@ -249,6 +269,18 @@ const char *elf_find_symbol(elf_t *e, uint32_t addr)
return c_map_at_end(e->symbols, &it) ? NULL : c_map_iter_value(&it, char *);
}

bool elf_get_data_section_range(elf_t *e, uint32_t *start, uint32_t *end)
{
const struct Elf32_Shdr *shdr = get_section_header(e, ".data");
if (!shdr)
return false;
if (shdr->sh_type == SHT_NOBITS)
return false;
*start = shdr->sh_addr;
*end = *start + shdr->sh_size;
return true;
}

bool elf_load(elf_t *e, struct riscv_t *rv, memory_t *mem)
{
rv_set_pc(rv, e->hdr->e_entry); /* set the entry point */
Expand Down
3 changes: 3 additions & 0 deletions elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,8 @@ const struct Elf32_Sym *elf_get_symbol(elf_t *e, const char *name);
/* Find symbole from a specified ELF file */
const char *elf_find_symbol(elf_t *e, uint32_t addr);

/* get the range of .data section from the ELF file */
bool elf_get_data_section_range(elf_t *e, uint32_t *start, uint32_t *end);

/* Load the ELF file into a memory abstraction */
bool elf_load(elf_t *e, struct riscv_t *rv, memory_t *mem);
53 changes: 52 additions & 1 deletion main.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
/* enable program trace mode */
static bool opt_trace = false;

/* RISCV arch-test*/
static bool opt_arch_test = false;
static char *signature_out_file;

/* target executable */
static const char *opt_prog_name = "a.out";

Expand Down Expand Up @@ -101,7 +105,9 @@ static void print_usage(const char *filename)
"RV32I[MA] Emulator which loads an ELF file to execute.\n"
"Usage: %s [options] [filename]\n"
"Options:\n"
" --trace : print executable trace\n",
" --trace : print executable trace\n"
" --arch-test [filename] : dump signature to the given file, "
"required by arch-test test\n",
filename);
}

Expand All @@ -118,6 +124,17 @@ static bool parse_args(int argc, char **args)
opt_trace = true;
continue;
}
if (!strcmp(arg, "--arch-test")) {
opt_arch_test = true;
if (i + 1 >= argc) {
fprintf(stderr,
"Filename for signature output required by "
"arch-test.\n");
return false;
}
signature_out_file = args[++i];
continue;
}
/* otherwise, error */
fprintf(stderr, "Unknown argument '%s'\n", arg);
return false;
Expand All @@ -129,6 +146,35 @@ static bool parse_args(int argc, char **args)
return true;
}

void dump_test_signature(struct riscv_t *rv, elf_t *elf)
{
uint32_t start = 0, end = 0;
const struct Elf32_Sym *sym;
FILE *f = fopen(signature_out_file, "w");
if (!f) {
fprintf(stderr, "Cannot open signature output file.\n");
return;
}

/* use the entire .data section as a fallback */
elf_get_data_section_range(elf, &start, &end);

/* try and access the exact signature range */
if ((sym = elf_get_symbol(elf, "begin_signature")))
start = sym->st_value;
if ((sym = elf_get_symbol(elf, "end_signature")))
end = sym->st_value;

state_t *s = rv_userdata(rv);

/* dump it word by word */
for (uint32_t addr = start; addr < end; addr += 4) {
fprintf(f, "%08x\n", memory_read_w(s->mem, addr));
}

fclose(f);
}

int main(int argc, char **args)
{
if (!parse_args(argc, args)) {
Expand Down Expand Up @@ -177,6 +223,11 @@ int main(int argc, char **args)
run(rv);
}

/* dump test result in test mode */
if (opt_arch_test) {
dump_test_signature(rv, elf);
}

/* finalize the RISC-V runtime */
elf_delete(elf);
rv_delete(rv);
Expand Down
1 change: 1 addition & 0 deletions riscv-arch-test
Submodule riscv-arch-test added at 307c77