Skip to content

Commit c9d4671

Browse files
committed
Compliance Test and ComputeGoTo Authored-by: sammer1107
1 parent 90879d5 commit c9d4671

File tree

15 files changed

+202
-5
lines changed

15 files changed

+202
-5
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
build/DOOM1.WAD*
22
shareware_doom_iwad.zip*
33
build/rv32emu
4+
build/compliance
45
*.o
56
*.o.d

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "riscv-compliance"]
2+
path = riscv-compliance
3+
url = https://github.com/riscv/riscv-compliance.git

Makefile

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,22 @@ LDFLAGS += `sdl2-config --libs`
2525
# Whether to enable computed goto in riscv.c
2626
ENABLE_COMPUTED_GOTO ?= 1
2727
ifeq ("$(ENABLE_COMPUTED_GOTO)", "1")
28+
<<<<<<< HEAD
29+
<<<<<<< HEAD
2830
ifneq ($(filter $(CC), gcc clang),)
31+
=======
32+
>>>>>>> Add support for clang in Makefile
33+
=======
34+
ifneq ($(filter $(CC), gcc clang),)
35+
>>>>>>> Improve compiler support for ENABLE_COMPUTED_GOTO
2936
riscv.o: CFLAGS += -D ENABLE_COMPUTED_GOTO
3037
ifeq ("$(CC)", "gcc")
3138
riscv.o: CFLAGS += -fno-gcse -fno-crossjumping
3239
endif
40+
<<<<<<< HEAD
41+
endif
42+
=======
43+
>>>>>>> Add support for clang in Makefile
3344
endif
3445
endif
3546

@@ -42,6 +53,12 @@ else
4253
VECHO = @printf
4354
endif
4455

56+
ifeq ("$(DEBUG)","1")
57+
CFLAGS += -ggdb -fno-omit-frame-pointer
58+
else
59+
CFLAGS += -O2
60+
endif
61+
4562
OUT ?= build
4663
BIN = $(OUT)/rv32emu
4764

@@ -58,6 +75,7 @@ OBJS = \
5875

5976
deps := $(OBJS:%.o=%.o.d)
6077

78+
6179
%.o: %.c
6280
$(VECHO) " CC\t$@\n"
6381
$(Q)$(CC) -o $@ $(CFLAGS) -c -MMD -MF $@.d $<
@@ -80,6 +98,19 @@ check: $(BIN)
8098
(cd $(OUT); ../$(BIN) hello.elf)
8199
(cd $(OUT); ../$(BIN) puzzle.elf)
82100

101+
# variables for compliance
102+
COMPLIANCE_DIR ?= ./riscv-compliance
103+
export RISCV_PREFIX ?= riscv32-unknown-elf-
104+
export RISCV_TARGET = test-rv32emu
105+
export TARGETDIR = $(shell pwd)
106+
export XLEN = 32
107+
export JOBS ?= -j
108+
export WORK = $(TARGETDIR)/build/compliance
109+
110+
compliance: $(BIN)
111+
$(Q)$(MAKE) --quiet -C $(COMPLIANCE_DIR) clean;
112+
$(Q)$(MAKE) --quiet -C $(COMPLIANCE_DIR);
113+
83114
demo: $(BIN) $(OUT)/DOOM1.WAD
84115
(cd $(OUT); ../$(BIN) doom.elf)
85116

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,17 @@ make demo
3030
The build script will then download data file for Doom automatically. SDL2 based window
3131
should appear when Doom is loaded and executed.
3232

33+
### Run riscv-compliance test
34+
Once the submodule `riscv-compliance` is pulled, run all the available compliance test via command:
35+
```shell
36+
make compliance
37+
```
38+
+ To run the tests for specific extension, set the environmental variable `RISCV_DEVICE` to one of `I`, `M`, `Zifencei`, `privilege`.
39+
+ To run a specific test case, set both `RISCV_DEVICE` and `RISCV_TEST`. For example:
40+
```shell
41+
make compliance RISCV_DEVICE=M RISCV_TEST=div-01
42+
```
43+
3344
## Customization
3445

3546
`rv32emu` is configurable, and you can modify `Makefile` to fit your expectations:

elf.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,26 @@ enum {
3434
STT_TLS = 6,
3535
};
3636

37+
enum {
38+
SHT_NULL = 0,
39+
SHT_PROGBITS = 1,
40+
SHT_SYMTAB = 2,
41+
SHT_STRTAB = 3,
42+
SHT_RELA = 4,
43+
SHT_HASH = 5,
44+
SHT_DYNAMIC = 6,
45+
SHT_NOTE = 7,
46+
SHT_NOBITS = 8,
47+
SHT_REL = 9,
48+
SHT_SHLIB = 10,
49+
SHT_DYNSYM = 11,
50+
SHT_NUM = 12,
51+
SHT_LOPROC = 0x70000000,
52+
SHT_HIPROC = 0x7fffffff,
53+
SHT_LOUSER = 0x80000000,
54+
SHT_HIUSER = 0xffffffff
55+
};
56+
3757
#define ELF_ST_TYPE(x) (((unsigned int) x) & 0xf)
3858

3959
struct Elf32_Ehdr {
@@ -249,6 +269,15 @@ const char *elf_find_symbol(elf_t *e, uint32_t addr)
249269
return c_map_at_end(e->symbols, &it) ? NULL : c_map_iter_value(&it, char *);
250270
}
251271

272+
bool elf_get_data_section_range(elf_t *e, uint32_t *start, uint32_t *end) {
273+
const struct Elf32_Shdr *shdr = get_section_header(e, ".data");
274+
if (!shdr) return false;
275+
if (shdr->sh_type == SHT_NOBITS) return false;
276+
*start = shdr->sh_addr;
277+
*end = *start + shdr->sh_size;
278+
return true;
279+
}
280+
252281
bool elf_load(elf_t *e, struct riscv_t *rv, memory_t *mem)
253282
{
254283
rv_set_pc(rv, e->hdr->e_entry); /* set the entry point */

elf.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,11 @@ bool elf_open(elf_t *e, const char *path);
4747
/* Find a symbol entry */
4848
const struct Elf32_Sym *elf_get_symbol(elf_t *e, const char *name);
4949

50-
/* Find symbole from a specified ELF file */
50+
/* Find symbol from a specified ELF file */
5151
const char *elf_find_symbol(elf_t *e, uint32_t addr);
5252

53+
/* get the range of .data section from the ELF file */
54+
bool elf_get_data_section_range(elf_t *e, uint32_t *start, uint32_t *end);
55+
5356
/* Load the ELF file into a memory abstraction */
5457
bool elf_load(elf_t *e, struct riscv_t *rv, memory_t *mem);

main.c

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
/* enable program trace mode */
99
static bool opt_trace = false;
1010

11+
/* RISCV compliance test mode */
12+
static bool opt_compliance = false;
13+
static char *signature_out_file;
14+
1115
/* target executable */
1216
static const char *opt_prog_name = "a.out";
1317

@@ -101,7 +105,8 @@ static void print_usage(const char *filename)
101105
"RV32I[MA] Emulator which loads an ELF file to execute.\n"
102106
"Usage: %s [options] [filename]\n"
103107
"Options:\n"
104-
" --trace : print executable trace\n",
108+
" --trace : print executable trace\n"
109+
" --compliance [signature filename] : dump signature to the given file for compliance test\n",
105110
filename);
106111
}
107112

@@ -118,6 +123,16 @@ static bool parse_args(int argc, char **args)
118123
opt_trace = true;
119124
continue;
120125
}
126+
if (!strcmp(arg, "--compliance")) {
127+
opt_compliance = true;
128+
if (i + 1 >= argc) {
129+
fprintf(stderr,
130+
"Filename for signature output required in compliance mode.\n");
131+
return false;
132+
}
133+
signature_out_file = args[++i];
134+
continue;
135+
}
121136
/* otherwise, error */
122137
fprintf(stderr, "Unknown argument '%s'\n", arg);
123138
return false;
@@ -129,6 +144,35 @@ static bool parse_args(int argc, char **args)
129144
return true;
130145
}
131146

147+
void dump_test_signature(struct riscv_t *rv, elf_t *elf)
148+
{
149+
uint32_t start = 0, end = 0;
150+
const struct Elf32_Sym *sym;
151+
FILE *f = fopen(signature_out_file, "w");
152+
if (!f) {
153+
fprintf(stderr, "Cannot open signature output file.\n");
154+
return;
155+
}
156+
157+
/* use the entire .data section as a fallback */
158+
elf_get_data_section_range(elf, &start, &end);
159+
/* try and access the exact signature range */
160+
if ((sym = elf_get_symbol(elf, "begin_signature")))
161+
start = sym->st_value;
162+
if ((sym = elf_get_symbol(elf, "end_signature")))
163+
end = sym->st_value;
164+
165+
state_t *s = rv_userdata(rv);
166+
167+
/* dump it word by word */
168+
for (uint32_t addr = start; addr < end; addr += 4) {
169+
fprintf(f, "%08x\n", memory_read_w(s->mem, addr));
170+
}
171+
172+
fclose(f);
173+
}
174+
175+
132176
int main(int argc, char **args)
133177
{
134178
if (!parse_args(argc, args)) {
@@ -177,6 +221,11 @@ int main(int argc, char **args)
177221
run(rv);
178222
}
179223

224+
/* dump test result in test mode */
225+
if (opt_compliance) {
226+
dump_test_signature(rv, elf);
227+
}
228+
180229
/* finalize the RISC-V runtime */
181230
elf_delete(elf);
182231
rv_delete(rv);

riscv-compliance

Submodule riscv-compliance added at 2e95f18

riscv.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -785,7 +785,7 @@ void rv_step(struct riscv_t *rv, int32_t cycles)
785785
assert(rv);
786786
const uint64_t cycles_target = rv->csr_cycle + cycles;
787787
uint32_t inst, index;
788-
788+
// clang-format off
789789
#define OP_UNIMP op_unimp
790790
#ifdef ENABLE_COMPUTED_GOTO
791791
#define OP(instr) &&op_##instr
@@ -795,7 +795,6 @@ void rv_step(struct riscv_t *rv, int32_t cycles)
795795
#define TABLE_TYPE const opcode_t
796796
#endif
797797

798-
// clang-format off
799798
TABLE_TYPE jump_table[] = {
800799
// 000 001 010 011 100 101 110 111
801800
OP(load), OP(load_fp), OP(unimp), OP(misc_mem), OP(op_imm), OP(auipc), OP(unimp), OP(unimp), // 00
@@ -830,10 +829,11 @@ void rv_step(struct riscv_t *rv, int32_t cycles)
830829
/* increment the cycles csr*/ \
831830
rv->csr_cycle++; \
832831
}
833-
832+
// clang-format off
834833
#define TARGET(instr) \
835834
op_##instr : EXEC(instr); \
836835
DISPATCH();
836+
// clang-format on
837837

838838
DISPATCH();
839839

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
RUN_TARGET= $(TARGETDIR)/build/rv32emu $(<) \
2+
$(RISCV_TARGET_FLAGS) \
3+
--compliance $(*).signature.output \
4+
1>$(@) 2>&1
5+
6+
RISCV_PREFIX ?= riscv32-unknown-elf-
7+
RISCV_GCC ?= $(RISCV_PREFIX)gcc
8+
RISCV_GCC_OPTS ?= \
9+
-march=rv32g \
10+
-mabi=ilp32 \
11+
-static \
12+
-mcmodel=medany \
13+
-fvisibility=hidden \
14+
$(RVTEST_DEFINES) \
15+
-nostdlib \
16+
-nostartfiles
17+
18+
COMPILE_TARGET=\
19+
$$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \
20+
-I$(ROOTDIR)/riscv-test-suite/env/ \
21+
-I$(TARGETDIR)/$(RISCV_TARGET)/ \
22+
-T$(TARGETDIR)/$(RISCV_TARGET)/link.ld \
23+
$$(<) -o $$(@);

0 commit comments

Comments
 (0)