1use crate::{
4 access::{Access, Read, Write},
5 endian::Endian,
6 reg::RegInt,
7};
8use core::{
9 fmt::Debug,
10 iter::{ExactSizeIterator, FusedIterator},
11 ops::{Bound, RangeBounds},
12};
13
14pub trait Memory: Sized {
16 type Memwidth: RegInt;
18 type Access: Access;
19 type Endian: Endian;
20
21 #[must_use]
22 fn first_entry_ptr(&self) -> *mut Self::Memwidth;
23
24 #[must_use]
26 fn num_entries(&self) -> usize;
27
28 #[must_use]
30 fn width(&self) -> usize;
31
32 #[must_use]
34 fn index(&self, idx: usize) -> MemEntry<Self> {
35 if idx < self.num_entries() {
36 unsafe { MemEntry::from_ptr(self.first_entry_ptr().wrapping_add(idx)) }
37 } else {
38 panic!(
39 "Tried to index {} in a memory with only {} entries",
40 idx,
41 self.num_entries()
42 );
43 }
44 }
45
46 #[must_use]
48 fn slice(&self, range: impl RangeBounds<usize>) -> MemEntryIter<Self> {
49 let low_idx = match range.start_bound() {
50 Bound::Included(idx) => *idx,
51 Bound::Excluded(idx) => *idx + 1,
52 Bound::Unbounded => 0,
53 };
54 let high_idx = match range.end_bound() {
55 Bound::Included(idx) => *idx,
56 Bound::Excluded(idx) => *idx - 1,
57 Bound::Unbounded => self.num_entries() - 1,
58 };
59 let num_entries = high_idx - low_idx + 1;
60 MemEntryIter {
61 next: self.index(low_idx),
62 remaining: num_entries,
63 }
64 }
65
66 #[must_use]
68 fn iter(&self) -> MemEntryIter<Self> {
69 self.slice(..)
70 }
71}
72
73#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
75pub struct MemEntry<M: Memory> {
76 ptr: *mut M::Memwidth,
77}
78
79impl<M: Memory> MemEntry<M> {
80 #[must_use]
85 pub const unsafe fn from_ptr(ptr: *mut M::Memwidth) -> Self {
86 Self { ptr }
87 }
88
89 #[must_use]
90 pub const fn as_ptr(&self) -> *mut M::Memwidth {
91 self.ptr
92 }
93}
94
95impl<M: Memory> MemEntry<M>
96where
97 M::Access: Read,
98{
99 #[must_use]
101 pub fn read(&self) -> M::Memwidth {
102 M::Endian::from_register_endian(unsafe { self.ptr.read_volatile() })
106 }
107}
108
109impl<M: Memory> MemEntry<M>
110where
111 M::Access: Write,
112{
113 pub fn write(&mut self, value: M::Memwidth) {
115 unsafe {
119 self.ptr
120 .write_volatile(M::Endian::to_register_endian(value));
121 }
122 }
123}
124
125#[derive(Debug)]
127pub struct MemEntryIter<M: Memory> {
128 next: MemEntry<M>,
129 remaining: usize,
130}
131
132impl<M: Memory> Iterator for MemEntryIter<M> {
133 type Item = MemEntry<M>;
134
135 fn next(&mut self) -> Option<Self::Item> {
136 if self.remaining == 0 {
137 None
138 } else {
139 self.remaining -= 1;
140 let new_next = unsafe { MemEntry::from_ptr(self.next.as_ptr().wrapping_add(1)) };
141 Some(core::mem::replace(&mut self.next, new_next))
142 }
143 }
144
145 fn size_hint(&self) -> (usize, Option<usize>) {
146 (self.remaining, Some(self.remaining))
147 }
148}
149
150impl<M: Memory> DoubleEndedIterator for MemEntryIter<M> {
151 fn next_back(&mut self) -> Option<Self::Item> {
152 if self.remaining == 0 {
153 None
154 } else {
155 self.remaining -= 1;
156 unsafe {
157 Some(MemEntry::from_ptr(
158 self.next.as_ptr().wrapping_add(self.remaining),
159 ))
160 }
161 }
162 }
163}
164
165impl<M: Memory> ExactSizeIterator for MemEntryIter<M> {}
166impl<M: Memory> FusedIterator for MemEntryIter<M> {}