From 945bf1e564542c039125025f03a7746459bb5e51 Mon Sep 17 00:00:00 2001 From: YEZZFUSL <18398621+yezzfusl@users.noreply.github.com> Date: Mon, 5 Aug 2024 20:06:09 -0400 Subject: [PATCH] Implement memory management unit for allocation and access. --- src/cpu.rs | 38 ++++++++++++++++++++++++++++---- src/memory.rs | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 4 deletions(-) create mode 100644 src/memory.rs diff --git a/src/cpu.rs b/src/cpu.rs index 41f1d12..adbde98 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -1,9 +1,13 @@ +// src/cpu.rs + use std::collections::HashMap; +mod memory; +use memory::MemoryManagementUnit; pub struct CPU { registers: [u32; 8], program_counter: usize, - memory: [u8; 4096], + mmu: MemoryManagementUnit, instruction_set: HashMap, } @@ -12,7 +16,7 @@ impl CPU { let mut cpu = CPU { registers: [0; 8], program_counter: 0, - memory: [0; 4096], + mmu: MemoryManagementUnit::new(), instruction_set: HashMap::new(), }; cpu.initialize_instruction_set(); @@ -24,6 +28,8 @@ impl CPU { self.instruction_set.insert(0x01, CPU::sub); self.instruction_set.insert(0x02, CPU::mul); self.instruction_set.insert(0x03, CPU::div); + self.instruction_set.insert(0x04, CPU::load); + self.instruction_set.insert(0x05, CPU::store); } pub fn run(&mut self) { @@ -34,7 +40,7 @@ impl CPU { } fn fetch(&mut self) -> u8 { - let instruction = self.memory[self.program_counter]; + let instruction = self.mmu.read_byte(self.program_counter); self.program_counter += 1; instruction } @@ -75,6 +81,16 @@ impl CPU { panic!("Division by zero"); } } + + fn load(&mut self, r1: u8, r2: u8, _r3: u8) { + let address = self.registers[r2 as usize] as usize; + self.registers[r1 as usize] = self.mmu.read_word(address); + } + + fn store(&mut self, r1: u8, r2: u8, _r3: u8) { + let address = self.registers[r2 as usize] as usize; + self.mmu.write_word(address, self.registers[r1 as usize]); + } } #[cfg(test)] @@ -125,5 +141,19 @@ mod tests { cpu.registers[1] = 0; cpu.div(0, 1, 0); } -} + #[test] + fn test_load_and_store_instructions() { + let mut cpu = CPU::new(); + cpu.registers[0] = 42; + cpu.registers[1] = 100; // memory address + + // Store value 42 at memory address 100 + cpu.store(0, 1, 0); + + // Load value from memory address 100 into register 2 + cpu.load(2, 1, 0); + + assert_eq!(cpu.registers[2], 42); + } +} diff --git a/src/memory.rs b/src/memory.rs new file mode 100644 index 0000000..bcfb862 --- /dev/null +++ b/src/memory.rs @@ -0,0 +1,61 @@ +// src/memory.rs + +pub struct MemoryManagementUnit { + memory: Vec, +} + +impl MemoryManagementUnit { + pub fn new() -> Self { + MemoryManagementUnit { + memory: vec![0; 65536], // 64KB of memory + } + } + + pub fn read_byte(&self, address: usize) -> u8 { + self.memory[address] + } + + pub fn write_byte(&mut self, address: usize, value: u8) { + self.memory[address] = value; + } + + pub fn read_word(&self, address: usize) -> u32 { + let bytes = &self.memory[address..address + 4]; + u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]) + } + + pub fn write_word(&mut self, address: usize, value: u32) { + let bytes = value.to_le_bytes(); + self.memory[address..address + 4].copy_from_slice(&bytes); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_read_write_byte() { + let mut mmu = MemoryManagementUnit::new(); + mmu.write_byte(0, 42); + assert_eq!(mmu.read_byte(0), 42); + } + + #[test] + fn test_read_write_word() { + let mut mmu = MemoryManagementUnit::new(); + mmu.write_word(0, 0x12345678); + assert_eq!(mmu.read_word(0), 0x12345678); + } + + #[test] + fn test_memory_persistence() { + let mut mmu = MemoryManagementUnit::new(); + mmu.write_byte(100, 1); + mmu.write_byte(101, 2); + mmu.write_byte(102, 3); + mmu.write_byte(103, 4); + + assert_eq!(mmu.read_word(100), 0x04030201); + } +}