1use std::collections::btree_map::BTreeMap;
6
7#[macro_use]
8mod register;
9
10pub use self::register::*;
11
12pub struct RegisterSpace {
14 regs: BTreeMap<RegisterRange, Box<dyn RegisterInterface>>,
15}
16
17impl RegisterSpace {
18 pub fn new() -> RegisterSpace {
20 RegisterSpace {
21 regs: BTreeMap::new(),
22 }
23 }
24
25 pub fn add_register<T: RegisterInterface + 'static>(&mut self, reg: T) {
27 let range = reg.range();
28 debug_assert!(self.get_register(range.from).is_none());
29 if cfg!(debug_assertions) {
30 if let Some(r) = self.first_before(range.to) {
31 debug_assert!(r.range().to < range.to);
32 }
33 }
34
35 let insert_result = self.regs.insert(range, Box::new(reg)).is_none();
36 debug_assert!(insert_result);
37 }
38
39 pub fn add_register_array<T: RegisterValue>(&mut self, regs: &[Register<T>]) {
41 for r in regs {
42 self.add_register(r.clone());
43 }
44 }
45
46 pub fn read(&self, addr: RegisterOffset, data: &mut [u8]) {
48 let mut current_addr: RegisterOffset = addr;
49 while current_addr < addr + data.len() as RegisterOffset {
50 if let Some(r) = self.get_register(current_addr) {
51 current_addr = r.range().to + 1;
53 r.read(addr, data);
54 } else {
55 current_addr += 1;
57 }
58 }
59 }
60
61 pub fn write(&self, addr: RegisterOffset, data: &[u8]) {
64 let mut current_addr: RegisterOffset = addr;
65 while current_addr < addr + data.len() as RegisterOffset {
66 if let Some(r) = self.get_register(current_addr) {
67 current_addr = r.range().to + 1;
69 r.write(addr, data);
70 } else {
71 current_addr += 1;
72 }
73 }
74 }
75
76 fn first_before(&self, addr: RegisterOffset) -> Option<&dyn RegisterInterface> {
78 for (range, r) in self.regs.iter().rev() {
79 if range.from <= addr {
80 return Some(r.as_ref());
81 }
82 }
83 None
84 }
85
86 fn get_register(&self, addr: RegisterOffset) -> Option<&dyn RegisterInterface> {
88 let r = self.first_before(addr)?;
89 let range = r.range();
90 if addr <= range.to {
91 Some(r)
92 } else {
93 None
94 }
95 }
96}
97
98#[cfg(test)]
99mod tests {
100 use std::sync::Arc;
101
102 use sync::Mutex;
103
104 use super::*;
105
106 #[test]
107 fn regs_no_reg() {
108 let regs = RegisterSpace::new();
109 let mut data: [u8; 4] = [4, 3, 2, 1];
110 regs.read(0, &mut data);
112 assert_eq!([4, 3, 2, 1], data);
113 regs.write(0, &[0, 0, 0, 0]);
115 regs.read(0, &mut data);
116 assert_eq!([4, 3, 2, 1], data);
117 }
118
119 #[test]
120 #[should_panic]
121 #[cfg(debug_assertions)]
122 fn regs_reg_overlap() {
123 let mut regs = RegisterSpace::new();
124 regs.add_register(static_register!(
125 ty: u32,
126 offset: 4,
127 value: 11,
128 ));
129
130 regs.add_register(static_register!(
131 ty: u16,
132 offset: 7,
133 value: 11,
134 ));
135 }
136
137 #[test]
138 fn regs_static_reg() {
139 let mut regs = RegisterSpace::new();
140 regs.add_register(static_register!(
141 ty: u8,
142 offset: 0,
143 value: 11,
144 ));
145 let mut data: [u8; 4] = [4, 3, 2, 1];
146 regs.read(0, &mut data);
147 assert_eq!([11, 3, 2, 1], data);
148 regs.write(0, &[0, 0, 0, 0]);
150 let mut data: [u8; 4] = [4, 3, 2, 1];
151 regs.read(0, &mut data);
152 assert_eq!([11, 3, 2, 1], data);
153 }
154
155 #[test]
156 fn regs_static_reg_offset() {
157 let mut regs = RegisterSpace::new();
158 regs.add_register(static_register!(
159 ty: u32,
160 offset: 2,
161 value: 0xaabbccdd,
162 ));
163 let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
164 regs.read(0, &mut data);
165 assert_eq!([8, 7, 0xdd, 0xcc, 0xbb, 0xaa, 2, 1], data);
166 regs.write(0, &[0, 0, 0, 0, 0, 0, 0, 0]);
168 let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
169 regs.read(0, &mut data);
170 assert_eq!([8, 7, 0xdd, 0xcc, 0xbb, 0xaa, 2, 1], data);
171 }
172
173 #[test]
174 fn regs_reg_write() {
175 let mut regs = RegisterSpace::new();
176 regs.add_register(register!(
177 name: "",
178 ty: u32,
179 offset: 2,
180 reset_value: 0xaabbccdd,
181 ));
182 let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
183 regs.read(0, &mut data);
184 assert_eq!([8, 7, 0xdd, 0xcc, 0xbb, 0xaa, 2, 1], data);
185 regs.write(0, &[0, 0, 0, 0, 0, 0, 0, 0]);
186 let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
187 regs.read(0, &mut data);
188 assert_eq!([8, 7, 0, 0, 0, 0, 2, 1], data);
189 }
190
191 #[test]
192 fn regs_reg_writeable() {
193 let mut regs = RegisterSpace::new();
194 regs.add_register(register!(
195 name: "",
196 ty: u32,
197 offset: 2,
198 reset_value: 0xaabbccdd,
199 guest_writeable_mask: 0x00f0000f,
200 guest_write_1_to_clear_mask: 0,
201 ));
202 let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
203 regs.read(0, &mut data);
204 assert_eq!([8, 7, 0xdd, 0xcc, 0xbb, 0xaa, 2, 1], data);
205 regs.write(0, &[0, 0, 0, 0, 0, 0, 0, 0]);
206 let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
207 regs.read(0, &mut data);
208 assert_eq!([8, 7, 0xd0, 0xcc, 0x0b, 0xaa, 2, 1], data);
209 }
210
211 #[test]
212 fn regs_reg_writeable_callback() {
213 let state = Arc::new(Mutex::new(0u32));
214 let mut regs = RegisterSpace::new();
215 let reg = register!(
216 name: "",
217 ty: u32,
218 offset: 2,
219 reset_value: 0xaabbccdd,
220 guest_writeable_mask: 0x00f0000f,
221 guest_write_1_to_clear_mask: 0,
222 );
223 regs.add_register(reg.clone());
224 let state_clone = state.clone();
225 reg.set_write_cb(move |val: u32| {
226 *state_clone.lock() = val;
227 val
228 });
229
230 let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
231 regs.read(0, &mut data);
232 assert_eq!([8, 7, 0xdd, 0xcc, 0xbb, 0xaa, 2, 1], data);
233 regs.write(0, &[0, 0, 0, 0, 0, 0, 0, 0]);
234 assert_eq!(0xaa0bccd0, *state.lock());
235 }
236
237 #[test]
238 fn regs_reg_write_to_clear() {
239 let mut regs = RegisterSpace::new();
240 regs.add_register(register!(
241 name: "",
242 ty: u32,
243 offset: 2,
244 reset_value: 0xaabbccdd,
245 guest_writeable_mask: 0xfff0000f,
246 guest_write_1_to_clear_mask: 0xf0000000,
247 ));
248 let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
249 regs.read(0, &mut data);
250 assert_eq!([8, 7, 0xdd, 0xcc, 0xbb, 0xaa, 2, 1], data);
251 regs.write(0, &[0, 0, 0, 0, 0, 0xad, 0, 0]);
252 let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
253 regs.read(0, &mut data);
254 assert_eq!([8, 7, 0xd0, 0xcc, 0x0b, 0x0d, 2, 1], data);
255 }
256
257 #[test]
258 fn regs_reg_array() {
259 let mut regs = RegisterSpace::new();
260 regs.add_register_array(®ister_array!(
261 name: "",
262 ty: u8,
263 cnt: 8,
264 base_offset: 10,
265 stride: 2,
266 reset_value: 0xff,
267 guest_writeable_mask: !0,
268 guest_write_1_to_clear_mask: 0,
269 ));
270 let mut data: [u8; 8] = [0; 8];
271 regs.read(8, &mut data);
272 assert_eq!([0, 0, 0xff, 0, 0xff, 0, 0xff, 0], data);
273 }
274
275 #[test]
276 fn regs_reg_multi_array() {
277 let mut regs = RegisterSpace::new();
278 regs.add_register_array(®ister_array!(
279 name: "",
280 ty: u8,
281 cnt: 8,
282 base_offset: 10,
283 stride: 2,
284 reset_value: 0xff,
285 guest_writeable_mask: !0,
286 guest_write_1_to_clear_mask: 0,
287 ));
288 regs.add_register_array(®ister_array!(
289 name: "",
290 ty: u8,
291 cnt: 8,
292 base_offset: 11,
293 stride: 2,
294 reset_value: 0xee,
295 guest_writeable_mask: !0,
296 guest_write_1_to_clear_mask: 0,
297 ));
298 let mut data: [u8; 8] = [0; 8];
299 regs.read(8, &mut data);
300 assert_eq!([0, 0, 0xff, 0xee, 0xff, 0xee, 0xff, 0xee], data);
301 }
302}