bitsy_lang/sim/ext/
ram.rs1use super::*;
2
3#[derive(Debug)]
8pub struct Ram {
9 mem: [u8; 1 << 16],
10 read_addr: u16,
11 write_enable: bool,
12 write_addr: u16,
13 write_data: u8,
14}
15
16impl Ram {
17 pub fn new() -> Ram {
18 let mem = [0; 1 << 16];
19 Ram {
20 mem,
21 read_addr: 0,
22 write_enable: false,
23 write_addr: 0,
24 write_data: 0,
25 }
26 }
27
28 pub fn load_from_file<P: AsRef<std::path::Path>>(&mut self, path: P) -> anyhow::Result<()> {
29 let data = std::fs::read(&path)?;
30 let len = data.len().min(1<<16);
31 for i in 0..len {
32 self.mem[i] = data[i];
33 }
34 Ok(())
35 }
36
37 fn read(&self) -> Value {
38 Value::Word(8, self.mem[self.read_addr as usize] as u64)
39 }
40
41 pub fn render(&self) -> String {
42 let mem = if let Some(index) = self.mem.iter().position(|&x| x == 0) {
44 &self.mem[..index+1]
45 } else {
46 &self.mem
47 };
48 format!("RAM: {:?}", String::from_utf8_lossy(mem))
49 }
50}
51
52impl ExtInstance for Ram {
53 fn incoming_ports(&self) -> Vec<PortName> {
54 vec![
55 "read_addr".to_string(),
56 "write_enable".to_string(),
57 "write_addr".to_string(),
58 "write_data".to_string(),
59 ]
60 }
61 fn outgoing_ports(&self) -> Vec<PortName> { vec!["read_data".to_string()] }
62
63 fn update(&mut self, port: &PortName, value: Value) -> Vec<(PortName, Value)> {
64 if value.is_x() {
65 return vec![("read_data".to_string(), self.read())];
66 }
67 if port == "read_addr" {
68 if let Value::Word(16, addr) = value {
69 self.read_addr = addr as u16;
70 return vec![("read_data".to_string(), self.read())];
71 } else {
72 panic!("Ram must receive a Word<16> on read_addr. Received {value:?}")
73 }
74 } else if port == "write_enable" {
75 match value {
76 Value::Word(1, 0) => self.write_enable = false,
77 Value::Word(1, 1) => self.write_enable = true,
78 _ => panic!(),
79 }
80 } else if port == "write_addr" {
81 match value {
82 Value::Word(16, v) => self.write_addr = v.try_into().unwrap(),
83 _ => panic!(),
84 }
85 } else if port == "write_data" {
86 match value {
87 Value::Word(8, v) => self.write_data = v.try_into().unwrap(),
88 _ => panic!("write_data value must be Word<8>: {value:?}"),
89 }
90 } else {
91 panic!("Ram may only recieve data on read_data: received data on {port} {value:?}")
92 }
93 vec![]
94 }
95
96 fn reset(&mut self) -> Vec<(PortName, Value)> {
97 vec![]
105 }
106
107 fn clock(&mut self) -> Vec<(PortName, Value)> {
108if self.write_enable {
110 println!("Writing to RAM: 0x{:04x} <= {:02x}", self.write_addr, self.write_data);
111 self.mem[self.write_addr as usize] = self.write_data;
112 let read_data = Value::Word(8, self.mem[self.read_addr as usize].into());
113 vec![("read_data".to_string(), read_data)]
115 } else {
116 vec![]
117 }
118 }
119}