From 1a317868503e188b11fce185709daadfa07b49f5 Mon Sep 17 00:00:00 2001 From: ZhuangYumin Date: Thu, 25 Jul 2024 03:48:16 +0000 Subject: [PATCH] finish writing interpreter, ready to debug --- .gitignore | 4 +- CMakeLists.txt | 15 + design.md | 1 + src/rv32iinterpreter.cpp | 900 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 919 insertions(+), 1 deletion(-) create mode 100644 design.md create mode 100644 src/rv32iinterpreter.cpp diff --git a/.gitignore b/.gitignore index 8a76a39..2d39a74 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ /.devcontainer /.github /.vscode -/build \ No newline at end of file +/build +/.cache +/.clang-format \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 49e6bdd..bd157af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,3 +14,18 @@ add_executable(alu demo/alu.cpp) # For debug build add_executable(modules demo/modules.cpp) target_compile_definitions(modules PRIVATE _DEBUG) + +add_executable(code src/rv32iinterpreter.cpp) +set_target_properties(code + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" +) + +# Enable sanitizer for debug builds +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") + set(SANITIZER_FLAGS "-fsanitize=address,undefined -fno-omit-frame-pointer") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${SANITIZER_FLAGS}") + set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${SANITIZER_FLAGS}") + endif() +endif() diff --git a/design.md b/design.md new file mode 100644 index 0000000..f652421 --- /dev/null +++ b/design.md @@ -0,0 +1 @@ +- step1: 完成一个RV32I interpreter(无需支持I-type的指令) \ No newline at end of file diff --git a/src/rv32iinterpreter.cpp b/src/rv32iinterpreter.cpp new file mode 100644 index 0000000..4c4e320 --- /dev/null +++ b/src/rv32iinterpreter.cpp @@ -0,0 +1,900 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +inline uint8_t ReadBit(uint32_t data, int pos) { return (data >> pos) & 1; } +inline void WriteBit(uint32_t &data, int pos, uint8_t bit) { + data &= ~(1 << pos); + data |= bit << pos; +} +class RV32IInterpreter; +typedef std::function ExecuteFunc; +void Execute_lui(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_auipc(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_jal(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_jalr(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_beq(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_bne(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_blt(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_bge(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_bltu(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_bgeu(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_lb(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_lh(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_lw(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_lbu(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_lhu(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_sb(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_sh(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_sw(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_addi(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_slti(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_sltiu(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_xori(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_ori(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_andi(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_slli(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_srli(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_srai(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_add(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_sub(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_sll(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_slt(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_sltu(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_xor(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_srl(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_sra(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_or(RV32IInterpreter &interpreter, uint32_t instruction); +void Execute_and(RV32IInterpreter &interpreter, uint32_t instruction); +std::map, ExecuteFunc> ExecuteFuncMap = { + {{0x37, 0}, Execute_lui}, {{0x17, 0}, Execute_auipc}, {{0x6F, 0}, Execute_jal}, {{0x67, 0}, Execute_jalr}, + {{0x63, 0}, Execute_beq}, {{0x63, 1}, Execute_bne}, {{0x63, 4}, Execute_blt}, {{0x63, 5}, Execute_bge}, + {{0x63, 6}, Execute_bltu}, {{0x63, 7}, Execute_bgeu}, {{0x03, 0}, Execute_lb}, {{0x03, 1}, Execute_lh}, + {{0x03, 2}, Execute_lw}, {{0x03, 4}, Execute_lbu}, {{0x03, 5}, Execute_lhu}, {{0x23, 0}, Execute_sb}, + {{0x23, 1}, Execute_sh}, {{0x23, 2}, Execute_sw}, {{0x13, 0}, Execute_addi}, {{0x13, 2}, Execute_slti}, + {{0x13, 3}, Execute_sltiu}, {{0x13, 4}, Execute_xori}, {{0x13, 6}, Execute_ori}, {{0x13, 7}, Execute_andi}, + {{0x13, 1}, Execute_slli}, {{0x13, 5}, Execute_srli}, {{0x13, 13}, Execute_srai}, {{0x33, 0}, Execute_add}, + {{0x33, 8}, Execute_sub}, {{0x33, 1}, Execute_sll}, {{0x33, 2}, Execute_slt}, {{0x33, 3}, Execute_sltu}, + {{0x33, 4}, Execute_xor}, {{0x33, 5}, Execute_srl}, {{0x33, 13}, Execute_sra}, {{0x33, 6}, Execute_or}, + {{0x33, 7}, Execute_and}}; +ExecuteFunc Decode(uint32_t instr) { + uint8_t opcode = instr & 127; + uint8_t funct3 = (instr >> 12) & 7; + uint8_t funct7 = (instr >> 25) & 127; + if (opcode == 0x37 || opcode == 0x17 || opcode == 0x6f) funct3 = 0; + funct7 >>= 5; + funct7 &= 3; + if (!(opcode == 0x13 && (funct3 == 1 || funct3 == 5)) && opcode != 0x33) { + funct7 = 0; + } + uint8_t second_key = funct3 | (funct7 << 3); + std::cerr << "Decoding, opcode=" << std::hex << (int)opcode << " second_key=" << std::dec << (int)second_key + << std::endl; + if (ExecuteFuncMap.find({opcode, second_key}) == ExecuteFuncMap.end()) { + throw std::runtime_error("Unsupported instruction"); + } + return ExecuteFuncMap[{opcode, second_key}]; +} +// no I type +class RV32IInterpreter { + std::vector dat; + uint8_t exit_code = 255; + uint32_t PC; + uint32_t IR; + uint32_t reg[32]; + size_t counter; + friend void Execute_lui(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_auipc(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_jal(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_jalr(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_beq(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_bne(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_blt(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_bge(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_bltu(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_bgeu(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_lb(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_lh(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_lw(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_lbu(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_lhu(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_sb(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_sh(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_sw(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_addi(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_slti(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_sltiu(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_xori(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_ori(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_andi(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_slli(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_srli(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_srai(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_add(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_sub(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_sll(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_slt(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_sltu(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_xor(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_srl(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_sra(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_or(RV32IInterpreter &interpreter, uint32_t instruction); + friend void Execute_and(RV32IInterpreter &interpreter, uint32_t instruction); + + public: + RV32IInterpreter() { + dat.reserve(1 << 20); + counter = 0; + } + void LoadProgram(std::istream &fin) { + fin >> std::hex; + std::string rubbish_bin; + do { + while (!fin.eof() && fin.get() != '@') + ; + if (fin.eof()) break; + int addr, tmp; + std::vector buf; + fin >> addr; + // std::cerr << "begin:" << std::hex << addr << std::endl; + while (fin >> tmp) { + buf.push_back(tmp); + } + if (dat.size() < addr + buf.size()) { + dat.resize(addr + buf.size()); + } + for (int i = 0; i < buf.size(); i++) { + dat[addr + i] = buf[i]; + // std::cerr << std::hex << addr + i << ' ' << std::uppercase << std::setw(2) << std::setfill('0') << std::hex + // << (int)buf[i] << std::endl; + } + fin.clear(); + } while (!fin.eof()); + PC = 0; + memset(reg, 0, sizeof(reg)); + } + bool Fetch() { + IR = *reinterpret_cast(&dat[PC]); + if (IR == 0x0FF00513) { + // std::cerr<<"ready to exit"<