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;
|
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)
|
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) {
|
void VM::setreg(int regnum, uint32_t value) {
|
||||||
if (regnum == 0) {
|
if (regnum == 0) {
|
||||||
|
@ -27,6 +23,22 @@ void VM::setreg(int regnum, uint32_t value) {
|
||||||
registers[regnum] = 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) {
|
void UART::read_mem(uint8_t* dst, size_t addr, size_t size) {
|
||||||
if (addr < UART_ADDR || addr + size > UART_ADDR + 8) {
|
if (addr < UART_ADDR || addr + size > UART_ADDR + 8) {
|
||||||
throw std::runtime_error("Memory access out of bounds");
|
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) {
|
void VM::read_mem(uint8_t* dst, size_t addr, size_t size) {
|
||||||
if (addr >= PROGRAM_ADDR) {
|
if (addr >= PROGRAM_ADDR) {
|
||||||
addr -= PROGRAM_ADDR;
|
ram.read_mem(dst, addr, size);
|
||||||
if (addr + size > memory_.size()) {
|
|
||||||
throw std::runtime_error("Memory access out of bounds");
|
|
||||||
}
|
|
||||||
std::memcpy(dst, &memory_[addr], size);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VM::write_mem(uint8_t* src, size_t addr, size_t size) {
|
void VM::write_mem(uint8_t* src, size_t addr, size_t size) {
|
||||||
if (addr >= PROGRAM_ADDR) {
|
if (addr >= PROGRAM_ADDR) {
|
||||||
addr -= PROGRAM_ADDR;
|
ram.write_mem(src, addr, size);
|
||||||
if (addr + size > memory_.size()) {
|
|
||||||
throw std::runtime_error("Memory access out of bounds");
|
|
||||||
}
|
|
||||||
std::memcpy(&memory_[addr], src, size);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_mmap(addr, size)) {
|
if (is_mmap(addr, size)) {
|
||||||
|
@ -128,7 +131,8 @@ const std::string& VM::get_file_path() { return file_path; }
|
||||||
|
|
||||||
void VM::step() {
|
void VM::step() {
|
||||||
if (pc < PROGRAM_ADDR) throw std::runtime_error("PC out of range");
|
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 << "pc: " << std::hex << pc << std::dec << "\n";
|
||||||
// std::cout << "instr: " << std::hex << instr << "\n";
|
// std::cout << "instr: " << std::hex << instr << "\n";
|
||||||
pc += 4;
|
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 UART_ADDR = 0x10000000;
|
||||||
const uint32_t PROGRAM_ADDR = 0x80000000;
|
const uint32_t PROGRAM_ADDR = 0x80000000;
|
||||||
|
|
||||||
class UART {
|
class Device {
|
||||||
public:
|
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);
|
virtual ~Device() = default;
|
||||||
void read_mem(uint8_t *dst, size_t addr, size_t size);
|
|
||||||
|
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:
|
private:
|
||||||
enum Registers {
|
enum Registers {
|
||||||
|
@ -28,8 +46,11 @@ class UART {
|
||||||
|
|
||||||
// Line Status Register bits
|
// Line Status Register bits
|
||||||
enum LSRBits { LSR_TRANSMITTER_EMPTY = 0x20 };
|
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 {
|
class VM {
|
||||||
|
@ -53,7 +74,7 @@ class VM {
|
||||||
void setreg(int regnum, uint32_t value);
|
void setreg(int regnum, uint32_t value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<uint8_t> memory_;
|
RAM ram;
|
||||||
|
|
||||||
uint32_t registers[NUM_REGISTERS] = {0};
|
uint32_t registers[NUM_REGISTERS] = {0};
|
||||||
uint32_t pc = 0;
|
uint32_t pc = 0;
|
||||||
|
|
Loading…
Reference in a new issue