Skip to content

Commit

Permalink
Add tests for all the instructions
Browse files Browse the repository at this point in the history
  • Loading branch information
mrexodia committed Jan 14, 2024
1 parent b03a771 commit a70b6cd
Show file tree
Hide file tree
Showing 76 changed files with 45,871 additions and 37 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
build*/
/*venv*/
*venv*/

*.bin
*.elf
Expand Down
33 changes: 33 additions & 0 deletions riscvm/CMakeLists.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 8 additions & 1 deletion riscvm/cmake.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ RISCVM_DEBUG_SYSCALLS = true

[target.riscvm]
type = "executable"
sources = ["riscvm.cpp"]
sources = ["main.cpp", "riscvm.cpp"]
headers = ["riscvm.h", "opcodes.h", "shuffled_opcodes.h", "trace.h"]
compile-features = ["cxx_std_17"]
RISCVM_DIRECT_DISPATCH.compile-definitions = ["DIRECT_DISPATCH"]
Expand All @@ -21,6 +21,13 @@ clang-cl.compile-options = ["/clang:-fno-jump-tables", "/clang:-mno-sse"]
clang.compile-options = ["-fno-jump-tables", "-mno-sse"]
msvc.link-options = ["/DYNAMICBASE:NO", "/INCREMENTAL:NO"]

[target.tests]
type = "executable"
sources = ["tests.cpp", "riscvm.cpp"]
compile-features = ["cxx_std_17"]
compile-definitions = ["DEBUG_SYSCALLS"]
msvc.link-options = ["/DYNAMICBASE:NO", "/INCREMENTAL:NO"]

# Only for IDE purposes, not actually built here
[target.riscvm-crt0]
type = "custom"
Expand Down
65 changes: 65 additions & 0 deletions riscvm/generate-isa-tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
from elftools.elf.elffile import ELFFile
from elftools.elf.sections import SymbolTableSection
import os

def parse_test_elf(file):
with open(file, "rb") as f:
elf = ELFFile(f)
# Enumerate the SymbolTableSection
for section in elf.iter_sections():
if isinstance(section, SymbolTableSection):
for i in range(section.num_symbols()):
symbol = section.get_symbol(i)
if symbol.name:
if symbol.name.startswith("test_"):
address = symbol.entry.st_value
# Convert address to file offset
offset = list(elf.address_offsets(address))[0]
return address, offset
return None, None


def main():
code = "#pragma once\n\n"
code += "#include <stdint.h>\n\n"
tests = []
directory = "isa-tests"
for file in sorted(os.listdir(directory)):
if file.startswith("rv64") and not file.endswith(".dump"):
path = os.path.join(directory, file)
address, offset = parse_test_elf(path)
if offset is None:
print(f"Failed to parse {file}")
continue
data = f"uint8_t {file.replace('-', '_')}_data[] = {{\n"
with open(path, "rb") as f:
# print the bytes in hex with max 32 bytes per line
for i, byte in enumerate(f.read()):
data += f"0x{byte:02x}, "
if i % 16 == 15:
data += "\n"
data += "\n};\n"
code += data
tests.append((file, address, offset))

code += "\n"
code += "struct Test {\n"
code += " const char* name;\n"
code += " uint8_t* data;\n"
code += " uint64_t size;\n"
code += " uint64_t address;\n"
code += " uint64_t offset;\n"
code += "};\n\n"

code += "static Test tests[] = {\n"
for name, address, offset in tests:
variable = f"{name.replace('-', '_')}_data"
code += f" {{ \"{name}\", {variable}, sizeof({variable}), {hex(address)}, {hex(offset)} }},\n"
code += "\n};\n"

with open("isa-tests/data.h", "wb") as f:
f.write(code.encode("utf-8"))


if __name__ == "__main__":
main()
1 change: 1 addition & 0 deletions riscvm/isa-tests/README.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Compiled from https://github.com/riscv-software-src/riscv-tests
45,638 changes: 45,638 additions & 0 deletions riscvm/isa-tests/data.h

Large diffs are not rendered by default.

Binary file added riscvm/isa-tests/rv64ui-p-add
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-addi
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-addiw
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-addw
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-and
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-andi
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-auipc
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-beq
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-bge
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-bgeu
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-blt
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-bltu
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-bne
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-fence_i
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-jal
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-jalr
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-lb
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-lbu
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-ld
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-lh
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-lhu
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-lui
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-lw
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-lwu
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-ma_data
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-or
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-ori
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-sb
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-sd
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-sh
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-simple
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-sll
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-slli
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-slliw
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-sllw
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-slt
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-slti
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-sltiu
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-sltu
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-sra
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-srai
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-sraiw
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-sraw
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-srl
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-srli
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-srliw
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-srlw
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-sub
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-subw
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-sw
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-xor
Binary file not shown.
Binary file added riscvm/isa-tests/rv64ui-p-xori
Binary file not shown.
Binary file added riscvm/isa-tests/rv64um-p-div
Binary file not shown.
Binary file added riscvm/isa-tests/rv64um-p-divu
Binary file not shown.
Binary file added riscvm/isa-tests/rv64um-p-divuw
Binary file not shown.
Binary file added riscvm/isa-tests/rv64um-p-divw
Binary file not shown.
Binary file added riscvm/isa-tests/rv64um-p-mul
Binary file not shown.
Binary file added riscvm/isa-tests/rv64um-p-mulh
Binary file not shown.
Binary file added riscvm/isa-tests/rv64um-p-mulhsu
Binary file not shown.
Binary file added riscvm/isa-tests/rv64um-p-mulhu
Binary file not shown.
Binary file added riscvm/isa-tests/rv64um-p-mulw
Binary file not shown.
Binary file added riscvm/isa-tests/rv64um-p-rem
Binary file not shown.
Binary file added riscvm/isa-tests/rv64um-p-remu
Binary file not shown.
Binary file added riscvm/isa-tests/rv64um-p-remuw
Binary file not shown.
Binary file added riscvm/isa-tests/rv64um-p-remw
Binary file not shown.
38 changes: 38 additions & 0 deletions riscvm/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include <cstring>
#include <cstddef>
#include <cstdlib>

#include "riscvm.h"

int main(int argc, char** argv)
{
if (argc < 2)
{
log("please supply a RV64I program to run!\n");
return EXIT_FAILURE;
}
riscvm_ptr machine = (riscvm_ptr)malloc(sizeof(riscvm));
memset(machine, 0, sizeof(riscvm));
riscvm_loadfile(machine, argv[1]);

#ifdef _DEBUG
g_trace = argc > 2 && _stricmp(argv[2], "--trace") == 0;
if (g_trace)
{
// TODO: allow custom trace file location/name
machine->trace = fopen("trace.txt", "w");
}
#endif // _DEBUG

riscvm_run(machine);
exit((int)machine->regs[reg_a0]);

#ifdef _DEBUG
if (g_trace)
{
fclose(machine->trace);
}
#endif // _DEBUG

return EXIT_SUCCESS;
}
40 changes: 7 additions & 33 deletions riscvm/riscvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#include "riscvm.h"
#include "trace.h"

bool g_trace;

#ifdef _WIN32
#pragma section(".vmcode", read, write)
__declspec(align(4096)) uint8_t g_code[0x10000];
Expand Down Expand Up @@ -238,6 +240,11 @@ ALWAYS_INLINE static bool riscvm_handle_syscall(riscvm_ptr self, uint64_t code,
printf("[syscall::print_tag_hex] %s: 0x%llx\n", (char*)reg_read(reg_a0), reg_read(reg_a1));
break;
}

case 0x5d: // linux exit
{
return false;
}
#endif // DEBUG_SYSCALLS

case 20000: // host_call
Expand Down Expand Up @@ -1190,36 +1197,3 @@ NEVER_INLINE void riscvm_run(riscvm_ptr self)
}
}
#endif // DIRECT_DISPATCH

int main(int argc, char** argv)
{
if (argc < 2)
{
log("please supply a RV64I program to run!\n");
return EXIT_FAILURE;
}
riscvm_ptr machine = (riscvm_ptr)malloc(sizeof(riscvm));
memset(machine, 0, sizeof(riscvm));
riscvm_loadfile(machine, argv[1]);

#ifdef _DEBUG
g_trace = argc > 2 && _stricmp(argv[2], "--trace") == 0;
if (g_trace)
{
// TODO: allow custom trace file location/name
machine->trace = fopen("trace.txt", "w");
}
#endif // _DEBUG

riscvm_run(machine);
exit((int)machine->regs[reg_a0]);

#ifdef _DEBUG
if (g_trace)
{
fclose(machine->trace);
}
#endif // _DEBUG

return EXIT_SUCCESS;
}
9 changes: 8 additions & 1 deletion riscvm/riscvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
#include <stdint.h>
#include <wchar.h>

extern uint8_t g_code[0x10000];
extern uint8_t g_stack[0x10000];

#ifdef _DEBUG

#define HAS_TRACE
static bool g_trace = false;
extern bool g_trace;

#define ALWAYS_INLINE
#define NEVER_INLINE
Expand Down Expand Up @@ -80,6 +83,7 @@ struct riscvm

#ifdef _DEBUG
FILE* trace;
int64_t rebase;
#endif // _DEBUG

#ifdef CODE_ENCRYPTION
Expand Down Expand Up @@ -269,3 +273,6 @@ ALWAYS_INLINE static int32_t bit_signer(uint32_t field, uint32_t size)
{
return (field & (1U << (size - 1))) ? (int32_t)(field | (0xFFFFFFFFU << size)) : (int32_t)field;
}

void riscvm_loadfile(riscvm_ptr self, const char* filename);
void riscvm_run(riscvm_ptr self);
71 changes: 71 additions & 0 deletions riscvm/tests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include <cstddef>
#include <memory>
#include <vector>

#include "riscvm.h"
#include "isa-tests/data.h"

int main(int argc, char** argv)
{
std::vector<const char*> filter;
for (int i = 1; i < argc; i++)
{
filter.push_back(argv[i]);
}
auto total = 0;
auto successful = 0;
for (const auto& test : tests)
{
if (!filter.empty())
{
auto allowed = false;
for (const auto& white : filter)
{
if (strcmp(test.name, white) == 0)
{
allowed = true;
break;
}
}
if (!allowed)
continue;
}

printf("[%s] ", test.name);
if (test.size > sizeof(g_code))
{
printf("ERROR (too big)\n", test.name);
continue;
}
total++;

memset(g_code, 0, sizeof(g_code));
memcpy(g_code, test.data, test.size);
riscvm vm = {};
auto self = &vm;
reg_write(reg_sp, (uint64_t)&g_stack[sizeof(g_stack) - 0x10]);
self->pc = (int64_t)g_code + test.offset;
#ifdef _DEBUG
g_trace = true;
char tracename[256] = "";
sprintf(tracename, "%s.trace", test.name);
self->trace = fopen(tracename, "w");
self->rebase = -self->pc + test.address;
#endif // _DEBUG
riscvm_run(self);
#ifdef _DEBUG
fclose(self->trace);
#endif // _DEBUG
auto status = (int)reg_read(reg_a0);
if (status != 0)
{
printf("FAILURE (status: %d)\n", status);
}
else
{
successful++;
printf("SUCCESS\n");
}
}
printf("\n%d/%d tests successful (%.2f%%)\n", successful, total, successful * 1.0f / total * 100);
}
2 changes: 1 addition & 1 deletion riscvm/trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ void riscvm_trace(riscvm_ptr self, Instruction inst)
return;
}

fprintf(self->trace, "[trace] 0x%016llx: ", self->pc);
fprintf(self->trace, "[trace] 0x%llx: ", self->pc + self->rebase);

for (int i = 0; i < calldepth; i++)
{
Expand Down

0 comments on commit a70b6cd

Please sign in to comment.