Fully generalize access to vram

This commit is contained in:
Konstantin Nazarov 2024-12-19 00:04:07 +00:00
parent 98a543b86c
commit 03bdb5091e
Signed by: knazarov
GPG key ID: 4CFE0A42FA409C22
2 changed files with 22 additions and 13 deletions

View file

@ -13,7 +13,11 @@ inline int32_t sign_extend(int32_t value, int bits) {
} }
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)
: ram(memory), pc(PROGRAM_ADDR), file_path(file_path) {} : ram(memory), pc(PROGRAM_ADDR), file_path(file_path) {
devices = std::vector<Device*>(2, 0);
devices[0] = &ram;
devices[1] = &uart;
}
void VM::setreg(int regnum, uint32_t value) { void VM::setreg(int regnum, uint32_t value) {
if (regnum == 0) { if (regnum == 0) {
@ -70,23 +74,24 @@ 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) { for (Device* dev : devices) {
ram.read_mem(dst, addr, size); if (addr >= dev->base() && addr + size <= dev->base() + dev->size()) {
dev->read_mem(dst, addr, size);
return;
} }
} }
throw std::runtime_error("Memory access out of bounds");
}
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) { for (Device* dev : devices) {
ram.write_mem(src, addr, size); if (addr >= dev->base() && addr + size <= dev->base() + dev->size()) {
} dev->write_mem(src, addr, size);
if (is_mmap(addr, size)) {
if (addr >= UART_ADDR && addr < UART_ADDR + 8) {
uart.write_mem(src, addr, size);
}
return; return;
} }
} }
throw std::runtime_error("Memory access out of bounds");
}
std::vector<uint8_t> VM::read_memory(size_t start, size_t size) { std::vector<uint8_t> VM::read_memory(size_t start, size_t size) {
std::vector<uint8_t> res(size, 0); std::vector<uint8_t> res(size, 0);

View file

@ -24,13 +24,16 @@ class Device {
virtual void write_mem(uint8_t *src, 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); virtual void read_mem(uint8_t *dst, size_t addr, size_t size);
uint32_t base() { return base_addr; }
uint32_t size() { return mem_size; }
private: private:
uint32_t base_addr = 0; uint32_t base_addr = 0;
uint32_t mem_size = 0; uint32_t mem_size = 0;
std::vector<uint8_t> mem; std::vector<uint8_t> mem;
}; };
class UART : public Device { class UART final : public Device {
public: public:
UART() : Device(UART_ADDR, 8) {} UART() : Device(UART_ADDR, 8) {}
@ -48,7 +51,7 @@ class UART : public Device {
enum LSRBits { LSR_TRANSMITTER_EMPTY = 0x20 }; enum LSRBits { LSR_TRANSMITTER_EMPTY = 0x20 };
}; };
class RAM : public Device { class RAM final : public Device {
public: public:
RAM(const std::vector<uint8_t> &memory) : Device(PROGRAM_ADDR, memory) {} RAM(const std::vector<uint8_t> &memory) : Device(PROGRAM_ADDR, memory) {}
}; };
@ -81,4 +84,5 @@ class VM {
std::string file_path; std::string file_path;
UART uart; UART uart;
std::vector<Device *> devices;
}; };