bitsy_lang/sim/ext/
mem.rs1use super::*;
2
3#[derive(Debug)]
8pub struct Mem {
9 mem: [u8; 1 << 16],
10 read_addr: u32,
11 write_enable: bool,
12 write_addr: u32,
13 write_data: u32
14}
15
16impl Mem {
17 pub fn new() -> Mem {
18 let mem = [0; 1 << 16];
19 Mem {
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 if self.read_addr >= 1<<16 {
39 return Value::Word(32, 0);
41 }
42 let val: u64 =
43 (self.mem[self.read_addr as usize] as u64) |
44 ((self.mem[self.read_addr as usize + 1] as u64) << 8) |
45 ((self.mem[self.read_addr as usize + 2] as u64) << 16) |
46 ((self.mem[self.read_addr as usize + 3] as u64) << 24)
47 ;
48 Value::Word(32, val)
49 }
50
51 pub fn render(&self) -> String {
52 let mem = if let Some(index) = self.mem.iter().position(|&x| x == 0) {
53 &self.mem[..index+1]
54 } else {
55 &self.mem
56 };
57 format!("RAM: {:?}", String::from_utf8_lossy(mem))
58 }
59}
60
61impl ExtInstance for Mem {
62 fn incoming_ports(&self) -> Vec<PortName> {
63 vec![
64 "read_addr".to_string(),
65 "write_enable".to_string(),
66 "write_addr".to_string(),
67 "write_data".to_string(),
68 ]
69 }
70 fn outgoing_ports(&self) -> Vec<PortName> { vec!["read_data".to_string()] }
71
72 fn update(&mut self, port: &PortName, value: Value) -> Vec<(PortName, Value)> {
73 if value.is_x() {
74 return vec![("read_data".to_string(), self.read())];
75 }
76 if port == "read_addr" {
77 if let Value::Word(32, addr) = value {
78 self.read_addr = addr as u32;
79 return vec![("read_data".to_string(), self.read())];
80 } else {
81 panic!("Mem must receive a Word<32> on read_addr. Received {value:?}")
82 }
83 } else if port == "write_enable" {
84 match value {
85 Value::Word(1, 0) => self.write_enable = false,
86 Value::Word(1, 1) => self.write_enable = true,
87 _ => panic!(),
88 }
89 } else if port == "write_addr" {
90 match value {
91 Value::Word(32, v) => self.write_addr = v.try_into().unwrap(),
92 _ => panic!("write_addr value must be Word<32>: {value:?}"),
93 }
94 } else if port == "write_data" {
95 match value {
96 Value::Word(32, v) => self.write_data = v.try_into().unwrap(),
97 _ => panic!("write_data value must be Word<32>: {value:?}"),
98 }
99 } else {
100 panic!("Mem may only recieve data on read_data: received data on {port} {value:?}")
101 }
102 vec![]
103 }
104
105 fn reset(&mut self) -> Vec<(PortName, Value)> {
106 vec![]
114 }
115
116 fn clock(&mut self) -> Vec<(PortName, Value)> {
117if self.write_enable {
119 println!("Writing to RAM: 0x{:08x} <= {:08x}", self.write_addr, self.write_data);
120 self.mem[self.write_addr as usize] = self.write_data as u8 & 0xff;
121 self.mem[(self.write_addr + 1) as usize] = (self.write_data >> 8) as u8;
122 self.mem[(self.write_addr + 2) as usize] = (self.write_data >> 16) as u8;
123 self.mem[(self.write_addr + 3) as usize] = (self.write_data >> 24) as u8;
124 let read_data = self.read();
125 vec![("read_data".to_string(), read_data)]
127 } else {
128 vec![]
129 }
130 }
131}
132