commit 06c5282c75d146fc0b2ff699af4086570ee02aa7 Author: Balazs Toldi Date: Wed Apr 12 22:08:20 2023 +0200 Initial commit Basic ADD operations are working, but nothing more. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8817525 --- /dev/null +++ b/.gitignore @@ -0,0 +1,68 @@ +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps + +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +build +test* +.vscode \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..1e52740 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,2 @@ +project(riscv_emu C) +add_executable(riscv_emu main.c riscv_emu.c) \ No newline at end of file diff --git a/main.c b/main.c new file mode 100644 index 0000000..aad8760 --- /dev/null +++ b/main.c @@ -0,0 +1,36 @@ +#include "riscv_emu.h" +#include +#include + +void loadFile(RiscvEmu *emu,char* file) { + size_t bytes = 0, readsz = MEMORY_SIZE; + FILE *fp = fopen (file, "rb"); + + if (!fp) { + fprintf (stderr, "error: file open failed '%s'.\n", file); + return; + } + + /* read/output BUFSZ bytes at a time */ + while ((bytes = fread (emu->memory, sizeof(uint8_t), readsz, fp)) == readsz) { + /* for (i = 0; i < readsz; i++) + printf (" 0x%02x", buf[i]); + putchar ('\n');*/ + } + + if (fp != stdin) + fclose (fp); +} + + +int main(void) { + RiscvEmu emu; + riscv_emu_init(&emu); + + printf("Initialized Risc-v processor!\n"); + printf("Loading Program...\n"); + loadFile(&emu,"test2"); + + riscv_emulate(&emu); + return 0; +} \ No newline at end of file diff --git a/riscv_emu.c b/riscv_emu.c new file mode 100644 index 0000000..df61f74 --- /dev/null +++ b/riscv_emu.c @@ -0,0 +1,123 @@ +#include "riscv_emu.h" +#include +#include + +void riscv_debug_print_binary(uint8_t num) +{ + for (int i = 7; i >= 0; i--) + { + printf("%c", (num & (1 << i)) ? '1' : '0'); + } + //printf("\n"); +} + +void riscv_debug_print_registers(RiscvEmu* emu) { + for (int i = 0; i < 32; i++) + { + printf("[r%d] => 0x%x\n", i,emu->registers[i]); + } +} + +void riscv_emu_init(RiscvEmu *emu) +{ + memset(emu->registers, 0, sizeof(emu->registers)); + memset(emu->memory, 0, sizeof(emu->memory)); + emu->pc = 0; +} + +void riscv_decode_instruction(uint32_t instr, RiscvInstruction *decoded_instr) +{ + decoded_instr->opcode = instr & 0x7F; + decoded_instr->rd = (instr >> 7) & 0x1F; + decoded_instr->funct3 = (instr >> 12) & 0x7; + decoded_instr->rs1 = (instr >> 15) & 0x1F; + decoded_instr->rs2 = (instr >> 20) & 0x1F; + decoded_instr->funct7 = (instr >> 25) & 0x7F; + + // Immediate field decoding + switch (decoded_instr->opcode) + { + case 0x03: // LOAD + case 0x13: // I-type + case 0x1B: // I-type (32-bit) + case 0x67: // JALR + decoded_instr->imm = (int32_t)(instr & 0xFFF00000) >> 20; + break; + + case 0x23: // STORE + case 0x33: // R-type + case 0x3B: // R-type (32-bit) + decoded_instr->imm = 0; + decoded_instr->rs1 = (instr >> 15) & 0x1F; + decoded_instr->rs2 = (instr >> 20) & 0x1F; + break; + + case 0x63: // B-type + decoded_instr->imm = ((instr >> 7) & 0x1E) | ((instr >> 20) & 0x7E0) | ((instr >> 20) & 0x800) | ((instr << 4) & 0x800); + decoded_instr->imm = (decoded_instr->imm ^ (1 << 12)) - (1 << 12); // Sign extend + break; + + case 0x6F: // JAL + decoded_instr->imm = (instr & 0xFF000) | ((instr >> 9) & 0x800) | ((instr >> 20) & 0x7FE); + decoded_instr->imm = (decoded_instr->imm ^ (1 << 20)) - (1 << 20); // Sign extend + break; + + default: + decoded_instr->imm = 0; + break; + } +} + +void riscv_execute_instruction(RiscvEmu *emu, RiscvInstruction instruction) +{ + switch (instruction.opcode) + { + case 0x13: + if (instruction.funct3 == 0x00) + { + printf("ADDI r%d, %d\n",instruction.rd-10,instruction.imm); + emu->registers[instruction.rd] +=instruction.imm; + } + break; + case 0x33: + if (instruction.funct3 == 0x00) + { + printf("ADD a%d, a%d, a%d\n",instruction.rd-10,instruction.rs1-10,instruction.rs2-10); + emu->registers[instruction.rd] = emu->registers[instruction.rs1] +emu->registers[instruction.rs2]; + } + break; + default: + printf("UNKOWN Instruction detected! opcode: "); + riscv_debug_print_binary(instruction.opcode); + printf(" func3: "); + riscv_debug_print_binary(instruction.funct3); + printf(" func7: "); + riscv_debug_print_binary(instruction.funct7); + printf("\n"); + break; + } +} + + + +void riscv_emulate(RiscvEmu *emu) +{ + int running = 1; + + while (running && emu->pc < 5) + { + // Fetch instruction + uint32_t instruction = *((uint32_t *)(emu->memory) + emu->pc); + + // Decode instruction + RiscvInstruction decoded_instr; + riscv_decode_instruction(instruction, &decoded_instr); + riscv_execute_instruction(emu, decoded_instr); + // Execute instruction (to be implemented) + // riscv_execuxte_instruction(emu, &decoded_instr); + + // Update program counter (to be implemented) + emu->pc++; + } + riscv_debug_print_registers(emu); +} \ No newline at end of file diff --git a/riscv_emu.h b/riscv_emu.h new file mode 100644 index 0000000..186e555 --- /dev/null +++ b/riscv_emu.h @@ -0,0 +1,31 @@ +#ifndef RISCV_EMU_H +#define RISCV_EMU_H + +#include + +#define NUM_REGISTERS 32 +#define MEMORY_SIZE 0x10000 // 64 KiB + +typedef struct { + uint32_t registers[NUM_REGISTERS]; // 32-bit general-purpose registers + uint32_t pc; // program counter + uint8_t memory[MEMORY_SIZE]; // memory +} RiscvEmu; + + +typedef struct { + uint8_t opcode; + uint8_t rd; + uint8_t funct3; + uint32_t rs1; + uint32_t rs2; + uint8_t funct7; + int32_t imm; +} RiscvInstruction; + + +void riscv_emu_init(RiscvEmu *emu); +void riscv_decode_instruction(uint32_t instr, RiscvInstruction *decoded_instr); +void riscv_emulate(RiscvEmu *emu); + +#endif