1use super::{MemAccessSize, Memory};
8use std::io;
9use std::io::Read;
10
11pub fn read_to_memory(
13 reader: impl Read,
14 memory: &mut impl Memory,
15 start_addr: u32,
16) -> io::Result<()> {
17 let mut write_addr = start_addr;
18 for b in reader.bytes() {
19 let b = b?;
20 if !memory.write_mem(write_addr, MemAccessSize::Byte, b as u32) {
21 return Err(io::Error::new(
22 io::ErrorKind::Other,
23 format!("Could not write byte at address 0x{:08x}", write_addr),
24 ));
25 }
26 write_addr += 1;
27 }
28
29 Ok(())
30}
31
32pub struct VecMemory {
37 pub mem: Vec<u32>,
38}
39
40impl VecMemory {
41 pub fn new(init_mem: Vec<u32>) -> VecMemory {
42 VecMemory { mem: init_mem }
43 }
44}
45
46impl Memory for VecMemory {
47 fn read_mem(&mut self, addr: u32, size: MemAccessSize) -> Option<u32> {
48 let (shift, mask) = match size {
50 MemAccessSize::Byte => (addr & 0x3, 0xff),
51 MemAccessSize::HalfWord => (addr & 0x2, 0xffff),
52 MemAccessSize::Word => (0, 0xffffffff),
53 };
54
55 if (addr & 0x3) != shift {
56 panic!("Memory read must be aligned");
57 }
58
59 let word_addr = addr >> 2;
61
62 let read_data = self.mem.get(word_addr as usize).copied()?;
64
65 Some((read_data >> (shift * 8)) & mask)
67 }
68
69 fn write_mem(&mut self, addr: u32, size: MemAccessSize, store_data: u32) -> bool {
70 let (shift, mask) = match size {
72 MemAccessSize::Byte => (addr & 0x3, 0xff),
73 MemAccessSize::HalfWord => (addr & 0x2, 0xffff),
74 MemAccessSize::Word => (0, 0xffffffff),
75 };
76
77 if (addr & 0x3) != shift {
78 panic!("Memory write must be aligned");
79 }
80
81 let write_mask = !(mask << (shift * 8));
83
84 let word_addr = (addr >> 2) as usize;
86
87 if let Some(update_data) = self.mem.get(word_addr) {
88 let new = (update_data & write_mask) | ((store_data & mask) << (shift * 8));
90 self.mem[word_addr] = new;
91 true
92 } else {
93 false
94 }
95 }
96}
97
98struct MemoryRegion {
99 base: u32,
100 size: u32,
101 memory: Box<dyn Memory>,
102}
103
104pub struct MemorySpace {
113 memory_regions: Vec<MemoryRegion>,
114}
115
116#[derive(Debug, PartialEq)]
117pub enum MemorySpaceError {
118 RegionOverlap,
119 Unaligned,
120}
121
122impl MemorySpace {
123 pub fn new() -> Self {
124 MemorySpace {
125 memory_regions: Vec::new(),
126 }
127 }
128
129 fn region_overlaps_existing(&self, base: u32, size: u32) -> bool {
131 for memory_region in self.memory_regions.iter() {
132 if base + size <= memory_region.base {
133 continue;
134 }
135
136 if memory_region.base + memory_region.size <= base {
137 continue;
138 }
139
140 return true;
141 }
142
143 false
144 }
145
146 fn get_memory_region_by_addr(&mut self, addr: u32) -> Option<&mut MemoryRegion> {
148 for memory_region in self.memory_regions.iter_mut() {
149 if (addr >= memory_region.base) && (addr < (memory_region.base + memory_region.size)) {
150 return Some(memory_region);
151 }
152 }
153
154 None
155 }
156
157 pub fn add_memory(
163 &mut self,
164 base: u32,
165 size: u32,
166 memory: Box<dyn Memory>,
167 ) -> Result<usize, MemorySpaceError> {
168 if ((base & 0x3) != 0) || ((size & 0x3) != 0) {
169 return Err(MemorySpaceError::Unaligned);
170 }
171
172 if self.region_overlaps_existing(base, size) {
173 return Err(MemorySpaceError::RegionOverlap);
174 }
175
176 let new_mem_index = self.memory_regions.len();
177 self.memory_regions
178 .push(MemoryRegion { base, size, memory });
179
180 Ok(new_mem_index)
181 }
182
183 pub fn get_memory_ref<T: Memory>(&self, index: usize) -> Option<&T> {
187 self.memory_regions.get(index)?.memory.downcast_ref::<T>()
188 }
189
190 pub fn get_memory_mut<T: Memory>(&mut self, index: usize) -> Option<&mut T> {
194 self.memory_regions
195 .get_mut(index)?
196 .memory
197 .downcast_mut::<T>()
198 }
199}
200
201impl Default for MemorySpace {
202 fn default() -> Self {
203 Self::new()
204 }
205}
206
207impl Memory for MemorySpace {
208 fn read_mem(&mut self, addr: u32, size: MemAccessSize) -> Option<u32> {
209 let memory_region = self.get_memory_region_by_addr(addr)?;
210
211 memory_region
212 .memory
213 .read_mem(addr - memory_region.base, size)
214 }
215
216 fn write_mem(&mut self, addr: u32, size: MemAccessSize, store_data: u32) -> bool {
217 if let Some(memory_region) = self.get_memory_region_by_addr(addr) {
218 memory_region
219 .memory
220 .write_mem(addr - memory_region.base, size, store_data)
221 } else {
222 false
223 }
224 }
225}
226
227#[cfg(test)]
228mod tests {
229 use super::*;
230 #[test]
231 fn test_vec_memory() {
232 let mut test_mem = VecMemory::new(vec![0xdeadbeef, 0xbaadf00d]);
233
234 assert_eq!(test_mem.read_mem(0x0, MemAccessSize::Byte), Some(0xef));
235
236 assert_eq!(test_mem.read_mem(0x5, MemAccessSize::Byte), Some(0xf0));
237
238 assert_eq!(
239 test_mem.read_mem(0x6, MemAccessSize::HalfWord),
240 Some(0xbaad)
241 );
242
243 assert_eq!(
244 test_mem.read_mem(0x4, MemAccessSize::Word),
245 Some(0xbaadf00d)
246 );
247
248 assert_eq!(test_mem.write_mem(0x7, MemAccessSize::Byte, 0xff), true);
249
250 assert_eq!(
251 test_mem.write_mem(0x2, MemAccessSize::HalfWord, 0xaaaaface),
252 true
253 );
254
255 assert_eq!(
256 test_mem.write_mem(0x1, MemAccessSize::Byte, 0x1234abcd),
257 true
258 );
259
260 assert_eq!(
261 test_mem.read_mem(0x0, MemAccessSize::Word),
262 Some(0xfacecdef)
263 );
264
265 assert_eq!(
266 test_mem.read_mem(0x4, MemAccessSize::Word),
267 Some(0xffadf00d)
268 );
269
270 assert_eq!(test_mem.read_mem(0x8, MemAccessSize::Word), None);
271
272 assert_eq!(test_mem.write_mem(0x8, MemAccessSize::Word, 0x0), false);
273 }
274
275 struct TestMemory;
276
277 impl Memory for TestMemory {
278 fn read_mem(&mut self, _addr: u32, _size: MemAccessSize) -> Option<u32> {
279 Some(0x1234abcd)
280 }
281
282 fn write_mem(&mut self, _addr: u32, _size: MemAccessSize, _store_data: u32) -> bool {
283 true
284 }
285 }
286
287 #[test]
288 fn test_memory_space() {
289 let mem_1_vec = vec![0x11111111, 0x22222222];
290 let mem_2_vec = vec![0x33333333, 0x44444444, 0x55555555];
291
292 let mut test_mem_space = MemorySpace::new();
293
294 assert_eq!(
295 test_mem_space.add_memory(0x100, 8, Box::new(VecMemory::new(mem_1_vec))),
296 Ok(0)
297 );
298
299 assert_eq!(
300 test_mem_space.add_memory(0x200, 12, Box::new(VecMemory::new(mem_2_vec))),
301 Ok(1)
302 );
303
304 assert_eq!(
305 test_mem_space.add_memory(0x300, 0x100, Box::new(TestMemory {})),
306 Ok(2)
307 );
308
309 assert_eq!(
310 test_mem_space.add_memory(0x280, 0x100, Box::new(TestMemory {})),
311 Err(MemorySpaceError::RegionOverlap)
312 );
313
314 assert_eq!(
315 test_mem_space.add_memory(0x280, 0x80, Box::new(TestMemory {})),
316 Ok(3)
317 );
318
319 assert_eq!(
320 test_mem_space.add_memory(0x403, 0x100, Box::new(TestMemory {})),
321 Err(MemorySpaceError::Unaligned)
322 );
323
324 assert_eq!(
325 test_mem_space.add_memory(0x400, 0x103, Box::new(TestMemory {})),
326 Err(MemorySpaceError::Unaligned)
327 );
328
329 assert!(test_mem_space.get_memory_ref::<VecMemory>(0).is_some());
330 assert!(test_mem_space.get_memory_ref::<TestMemory>(0).is_none());
331 assert!(test_mem_space.get_memory_mut::<TestMemory>(2).is_some());
332 assert!(test_mem_space.get_memory_mut::<TestMemory>(1).is_none());
333
334 assert_eq!(
335 test_mem_space.read_mem(0x100, MemAccessSize::Word),
336 Some(0x11111111)
337 );
338
339 assert_eq!(
340 test_mem_space.read_mem(0x204, MemAccessSize::Word),
341 Some(0x44444444)
342 );
343
344 assert_eq!(
345 test_mem_space.write_mem(0x208, MemAccessSize::Word, 0xffffffff),
346 true
347 );
348
349 assert_eq!(
350 test_mem_space.write_mem(0x20c, MemAccessSize::Word, 0xffffffff),
351 false
352 );
353
354 assert_eq!(test_mem_space.read_mem(0x108, MemAccessSize::Word), None);
355
356 for i in 0..0x40 {
357 assert_eq!(
358 test_mem_space.read_mem(i * 4 + 0x300, MemAccessSize::Word),
359 Some(0x1234abcd)
360 );
361 }
362
363 assert_eq!(test_mem_space.read_mem(0x400, MemAccessSize::Word), None);
364
365 assert_eq!(
366 test_mem_space.get_memory_ref::<VecMemory>(1).unwrap().mem[2],
367 0xffffffff
368 );
369
370 test_mem_space.get_memory_mut::<VecMemory>(0).unwrap().mem[0] = 0xdeadbeef;
371
372 assert_eq!(
373 test_mem_space.read_mem(0x100, MemAccessSize::Word),
374 Some(0xdeadbeef)
375 );
376 }
377
378 #[test]
379 fn test_read_to_memory() {
380 let test_bytes: Vec<u8> = (5..21).collect();
381 let mut test_memory = VecMemory::new(vec![0; 4]);
382
383 assert!(read_to_memory(test_bytes.as_slice(), &mut test_memory, 0).is_ok());
384
385 for a in 0..16 {
386 assert_eq!(test_memory.read_mem(a, MemAccessSize::Byte), Some(a + 5));
387 }
388
389 let test_bytes: Vec<u8> = (10..15).collect();
390
391 assert!(read_to_memory(test_bytes.as_slice(), &mut test_memory, 5).is_ok());
392
393 for a in 5..10 {
394 assert_eq!(test_memory.read_mem(a, MemAccessSize::Byte), Some(a + 5));
395 }
396
397 assert_eq!(
398 format!(
399 "{:?}",
400 read_to_memory(test_bytes.as_slice(), &mut test_memory, 13)
401 .unwrap_err()
402 .get_ref()
403 .unwrap()
404 ),
405 "\"Could not write byte at address 0x00000010\""
406 );
407 }
408}