Make RAM a regular device

This commit is contained in:
Konstantin Nazarov 2024-12-18 23:47:27 +00:00
parent dfc9b2824e
commit 98a543b86c
Signed by: knazarov
GPG key ID: 4CFE0A42FA409C22
2 changed files with 48 additions and 23 deletions

View file

@ -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;

View file

@ -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;