Initial commit
Basic ADD operations are working, but nothing more.
This commit is contained in:
commit
06c5282c75
5 changed files with 260 additions and 0 deletions
68
.gitignore
vendored
Normal file
68
.gitignore
vendored
Normal file
|
@ -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
|
2
CMakeLists.txt
Normal file
2
CMakeLists.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
project(riscv_emu C)
|
||||
add_executable(riscv_emu main.c riscv_emu.c)
|
36
main.c
Normal file
36
main.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
#include "riscv_emu.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
}
|
123
riscv_emu.c
Normal file
123
riscv_emu.c
Normal file
|
@ -0,0 +1,123 @@
|
|||
#include "riscv_emu.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
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);
|
||||
}
|
31
riscv_emu.h
Normal file
31
riscv_emu.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
#ifndef RISCV_EMU_H
|
||||
#define RISCV_EMU_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#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
|
Loading…
Reference in a new issue