2022-02-20 14:25:43 -06:00
|
|
|
use crate::word::Word;
|
|
|
|
|
use crate::word::MEM_SIZE;
|
2022-02-22 21:46:26 -06:00
|
|
|
use rand::Rng;
|
2022-02-18 21:02:17 -06:00
|
|
|
|
|
|
|
|
pub struct Memory([u8; MEM_SIZE as usize]);
|
|
|
|
|
|
|
|
|
|
impl Default for Memory {
|
2022-02-22 21:46:26 -06:00
|
|
|
fn default() -> Self {
|
|
|
|
|
Self([0u8; MEM_SIZE as usize])
|
|
|
|
|
}
|
2022-02-18 21:02:17 -06:00
|
|
|
}
|
|
|
|
|
|
2022-02-18 22:32:37 -06:00
|
|
|
impl From<Word> for usize {
|
|
|
|
|
fn from(w: Word) -> Self {
|
|
|
|
|
let w: u32 = w.into();
|
2022-02-22 21:46:26 -06:00
|
|
|
(w & (MEM_SIZE - 1)) as usize
|
2022-02-18 22:32:37 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-18 21:02:17 -06:00
|
|
|
impl<R: Rng> From<R> for Memory {
|
|
|
|
|
fn from(mut rng: R) -> Self {
|
|
|
|
|
let mut mem = Memory::default();
|
|
|
|
|
for i in 0..(MEM_SIZE - 1) {
|
|
|
|
|
mem.0[i as usize] = rng.gen()
|
|
|
|
|
}
|
|
|
|
|
mem
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-18 22:32:37 -06:00
|
|
|
impl std::ops::Index<Word> for Memory {
|
2022-02-18 21:02:17 -06:00
|
|
|
type Output = u8;
|
2022-02-18 22:32:37 -06:00
|
|
|
fn index(&self, index: Word) -> &Self::Output {
|
|
|
|
|
&self.0[usize::from(index)]
|
|
|
|
|
}
|
2022-02-18 21:02:17 -06:00
|
|
|
}
|
|
|
|
|
|
2022-02-18 22:32:37 -06:00
|
|
|
impl std::ops::IndexMut<Word> for Memory {
|
|
|
|
|
fn index_mut(&mut self, index: Word) -> &mut Self::Output {
|
|
|
|
|
&mut self.0[usize::from(index)]
|
|
|
|
|
}
|
2022-02-18 21:02:17 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub trait PeekPoke {
|
2022-02-19 11:13:27 -06:00
|
|
|
fn peek(&self, addr: Word) -> u8;
|
|
|
|
|
fn poke(&mut self, addr: Word, val: u8);
|
2022-02-18 21:02:17 -06:00
|
|
|
|
2022-02-19 11:13:27 -06:00
|
|
|
fn peek24(&self, addr: Word) -> u32 {
|
2022-02-18 22:32:37 -06:00
|
|
|
(self.peek(addr) as u32)
|
|
|
|
|
| ((self.peek(addr + 1) as u32) << 8)
|
|
|
|
|
| ((self.peek(addr + 2) as u32) << 16)
|
2022-02-18 21:02:17 -06:00
|
|
|
}
|
|
|
|
|
|
2022-02-19 11:13:27 -06:00
|
|
|
fn poke24(&mut self, addr: Word, val: u32) {
|
2022-02-18 21:02:17 -06:00
|
|
|
self.poke(addr, val as u8);
|
|
|
|
|
self.poke(addr + 1, (val >> 8) as u8);
|
|
|
|
|
self.poke(addr + 2, (val >> 16) as u8);
|
|
|
|
|
}
|
2022-02-19 11:13:27 -06:00
|
|
|
|
2022-02-22 21:46:26 -06:00
|
|
|
fn peek_u32(&self, addr: u32) -> u8 {
|
|
|
|
|
self.peek(addr.into())
|
|
|
|
|
}
|
|
|
|
|
fn poke_u32(&mut self, addr: u32, val: u8) {
|
|
|
|
|
self.poke(addr.into(), val)
|
|
|
|
|
}
|
|
|
|
|
fn peek24_u32(&mut self, addr: u32) -> u32 {
|
|
|
|
|
self.peek24(addr.into())
|
|
|
|
|
}
|
|
|
|
|
fn poke24_u32(&mut self, addr: u32, val: u32) {
|
|
|
|
|
self.poke24(addr.into(), val)
|
|
|
|
|
}
|
2022-02-18 21:02:17 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl PeekPoke for Memory {
|
2022-02-22 21:46:26 -06:00
|
|
|
fn peek(&self, addr: Word) -> u8 {
|
|
|
|
|
self[addr]
|
|
|
|
|
}
|
|
|
|
|
fn poke(&mut self, addr: Word, val: u8) {
|
|
|
|
|
self[addr] = val;
|
|
|
|
|
}
|
2022-02-18 21:02:17 -06:00
|
|
|
}
|
|
|
|
|
|
2022-02-18 22:32:37 -06:00
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests {
|
|
|
|
|
use super::*;
|
2022-02-18 21:02:17 -06:00
|
|
|
|
2022-02-18 22:32:37 -06:00
|
|
|
#[test]
|
|
|
|
|
fn test_mem_peek_poke() {
|
|
|
|
|
let mut mem = Memory::default();
|
2022-02-19 11:13:27 -06:00
|
|
|
assert_eq!(mem.peek_u32(35), 0);
|
|
|
|
|
mem.poke_u32(35, 45);
|
|
|
|
|
assert_eq!(mem.peek_u32(35), 45);
|
|
|
|
|
assert_eq!(mem.peek_u32(36), 0);
|
2022-02-18 22:32:37 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_mem_word_fns() {
|
|
|
|
|
let mut mem = Memory::default();
|
2022-02-19 11:13:27 -06:00
|
|
|
mem.poke24(10.into(), 0x123456);
|
|
|
|
|
assert_eq!(mem.peek_u32(10), 0x56);
|
|
|
|
|
assert_eq!(mem.peek_u32(11), 0x34);
|
|
|
|
|
assert_eq!(mem.peek_u32(12), 0x12);
|
|
|
|
|
assert_eq!(mem.peek24(10.into()), 0x123456);
|
|
|
|
|
assert_eq!(mem.peek24(11.into()), 0x001234);
|
2022-02-18 22:32:37 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_addressing_arrays() {
|
|
|
|
|
let a: usize = Word::from(0xffffff).into();
|
|
|
|
|
assert_eq!(a, 0x01ffff as usize);
|
|
|
|
|
}
|
2022-02-18 21:02:17 -06:00
|
|
|
}
|