Make RAM a regular device
This commit is contained in:
parent
dfc9b2824e
commit
98a543b86c
2 changed files with 48 additions and 23 deletions
38
src/vm.cpp
38
src/vm.cpp
|
@ -12,12 +12,8 @@ inline int32_t sign_extend(int32_t value, int bits) {
|
|||
return (value ^ mask) - mask;
|
||||
}
|
||||
|
||||
bool UART::is_transmitter_ready() {
|
||||
return registers[UART_LSR] & LSR_TRANSMITTER_EMPTY;
|
||||
}
|
||||
|
||||
VM::VM(const std::vector<uint8_t>& memory, const std::string& file_path)
|
||||
: memory_(memory), pc(PROGRAM_ADDR), file_path(file_path) {}
|
||||
: ram(memory), pc(PROGRAM_ADDR), file_path(file_path) {}
|
||||
|
||||
void VM::setreg(int regnum, uint32_t value) {
|
||||
if (regnum == 0) {
|
||||
|
@ -27,6 +23,22 @@ void VM::setreg(int regnum, uint32_t value) {
|
|||
registers[regnum] = value;
|
||||
}
|
||||
|
||||
void Device::write_mem(uint8_t* src, size_t addr, size_t size) {
|
||||
if (addr < base_addr || addr + size > base_addr + mem_size) {
|
||||
throw std::runtime_error("Memory access out of bounds");
|
||||
}
|
||||
addr -= base_addr;
|
||||
std::memcpy(&mem[addr], src, size);
|
||||
}
|
||||
|
||||
void Device::read_mem(uint8_t* dst, size_t addr, size_t size) {
|
||||
if (addr < base_addr || addr + size > base_addr + mem_size) {
|
||||
throw std::runtime_error("Memory access out of bounds");
|
||||
}
|
||||
addr -= base_addr;
|
||||
std::memcpy(dst, &mem[addr], size);
|
||||
}
|
||||
|
||||
void UART::read_mem(uint8_t* dst, size_t addr, size_t size) {
|
||||
if (addr < UART_ADDR || addr + size > UART_ADDR + 8) {
|
||||
throw std::runtime_error("Memory access out of bounds");
|
||||
|
@ -59,22 +71,13 @@ void UART::write_mem(uint8_t* src, size_t addr, size_t size) {
|
|||
|
||||
void VM::read_mem(uint8_t* dst, size_t addr, size_t size) {
|
||||
if (addr >= PROGRAM_ADDR) {
|
||||
addr -= PROGRAM_ADDR;
|
||||
if (addr + size > memory_.size()) {
|
||||
throw std::runtime_error("Memory access out of bounds");
|
||||
}
|
||||
std::memcpy(dst, &memory_[addr], size);
|
||||
ram.read_mem(dst, addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
void VM::write_mem(uint8_t* src, size_t addr, size_t size) {
|
||||
if (addr >= PROGRAM_ADDR) {
|
||||
addr -= PROGRAM_ADDR;
|
||||
if (addr + size > memory_.size()) {
|
||||
throw std::runtime_error("Memory access out of bounds");
|
||||
}
|
||||
std::memcpy(&memory_[addr], src, size);
|
||||
return;
|
||||
ram.write_mem(src, addr, size);
|
||||
}
|
||||
|
||||
if (is_mmap(addr, size)) {
|
||||
|
@ -128,7 +131,8 @@ const std::string& VM::get_file_path() { return file_path; }
|
|||
|
||||
void VM::step() {
|
||||
if (pc < PROGRAM_ADDR) throw std::runtime_error("PC out of range");
|
||||
uint32_t instr = *(uint32_t*)&memory_[pc - PROGRAM_ADDR];
|
||||
uint32_t instr;
|
||||
read_mem((uint8_t*)&instr, pc, 4);
|
||||
// std::cout << "pc: " << std::hex << pc << std::dec << "\n";
|
||||
// std::cout << "instr: " << std::hex << instr << "\n";
|
||||
pc += 4;
|
||||
|
|
33
src/vm.hpp
33
src/vm.hpp
|
@ -12,12 +12,30 @@ const int NUM_REGISTERS = 32; // Standard RISC-V has 32 registers
|
|||
const uint32_t UART_ADDR = 0x10000000;
|
||||
const uint32_t PROGRAM_ADDR = 0x80000000;
|
||||
|
||||
class UART {
|
||||
class Device {
|
||||
public:
|
||||
bool is_transmitter_ready();
|
||||
Device(uint32_t base_addr, uint32_t mem_size)
|
||||
: base_addr(base_addr), mem_size(mem_size), mem(mem_size, 0) {}
|
||||
Device(uint32_t base_addr, const std::vector<uint8_t> &memory)
|
||||
: base_addr(base_addr), mem_size(memory.size()), mem(memory) {}
|
||||
|
||||
void write_mem(uint8_t *src, size_t addr, size_t size);
|
||||
void read_mem(uint8_t *dst, size_t addr, size_t size);
|
||||
virtual ~Device() = default;
|
||||
|
||||
virtual void write_mem(uint8_t *src, size_t addr, size_t size);
|
||||
virtual void read_mem(uint8_t *dst, size_t addr, size_t size);
|
||||
|
||||
private:
|
||||
uint32_t base_addr = 0;
|
||||
uint32_t mem_size = 0;
|
||||
std::vector<uint8_t> mem;
|
||||
};
|
||||
|
||||
class UART : public Device {
|
||||
public:
|
||||
UART() : Device(UART_ADDR, 8) {}
|
||||
|
||||
virtual void write_mem(uint8_t *src, size_t addr, size_t size);
|
||||
virtual void read_mem(uint8_t *dst, size_t addr, size_t size);
|
||||
|
||||
private:
|
||||
enum Registers {
|
||||
|
@ -28,8 +46,11 @@ class UART {
|
|||
|
||||
// Line Status Register bits
|
||||
enum LSRBits { LSR_TRANSMITTER_EMPTY = 0x20 };
|
||||
};
|
||||
|
||||
uint8_t registers[8] = {0};
|
||||
class RAM : public Device {
|
||||
public:
|
||||
RAM(const std::vector<uint8_t> &memory) : Device(PROGRAM_ADDR, memory) {}
|
||||
};
|
||||
|
||||
class VM {
|
||||
|
@ -53,7 +74,7 @@ class VM {
|
|||
void setreg(int regnum, uint32_t value);
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> memory_;
|
||||
RAM ram;
|
||||
|
||||
uint32_t registers[NUM_REGISTERS] = {0};
|
||||
uint32_t pc = 0;
|
||||
|
|
Loading…
Reference in a new issue