1use crate::{Mmio, MmioExt, MmioOperand};
11
12use std::marker::PhantomData;
13
14pub struct RegisterProxy<'a, M: Mmio + ?Sized, R: Register> {
19 mmio: &'a M,
20 _phantom: PhantomData<R>,
21}
22
23impl<'a, M: Mmio + ?Sized, R: Register> RegisterProxy<'a, M, R> {
24 pub fn new(mmio: &'a M) -> Self {
26 Self { mmio, _phantom: PhantomData }
27 }
28}
29
30impl<'a, M: Mmio + ?Sized, R: ReadableRegister> RegisterProxy<'a, M, R> {
31 pub fn read(&self) -> R {
33 R::read(self.mmio)
34 }
35}
36
37pub struct RegisterProxyMut<'a, M: Mmio + ?Sized, R: Register> {
39 mmio: &'a mut M,
40 _phantom: PhantomData<R>,
41}
42
43impl<'a, M: Mmio + ?Sized, R: Register> RegisterProxyMut<'a, M, R> {
44 pub fn new(mmio: &'a mut M) -> Self {
46 Self { mmio, _phantom: PhantomData }
47 }
48}
49
50impl<'a, M: Mmio + ?Sized, R: ReadableRegister> RegisterProxyMut<'a, M, R> {
51 pub fn read(&self) -> R {
53 R::read(self.mmio)
54 }
55}
56
57impl<'a, M: Mmio + ?Sized, R: WritableRegister> RegisterProxyMut<'a, M, R> {
58 pub fn write(&mut self, val: R) {
60 val.write(self.mmio)
61 }
62}
63
64impl<'a, M: Mmio + ?Sized, R: ReadableRegister + WritableRegister> RegisterProxyMut<'a, M, R> {
65 pub fn update<F: FnOnce(&mut R)>(&mut self, f: F) {
67 let mut reg = self.read();
68 f(&mut reg);
69 self.write(reg);
70 }
71}
72
73pub struct IndexedRegisterProxy<'a, M: Mmio + ?Sized, R: IndexedRegister> {
75 mmio: &'a M,
76 _phantom: PhantomData<R>,
77}
78
79impl<'a, M: Mmio + ?Sized, R: IndexedRegister> IndexedRegisterProxy<'a, M, R> {
80 pub fn new(mmio: &'a M) -> Self {
82 Self { mmio, _phantom: PhantomData }
83 }
84}
85
86impl<'a, M: Mmio + ?Sized, R: ReadableIndexedRegister> IndexedRegisterProxy<'a, M, R> {
87 pub fn read(&self, index: usize) -> R {
89 R::read_index(self.mmio, index)
90 }
91}
92
93pub struct IndexedRegisterProxyMut<'a, M: Mmio + ?Sized, R: IndexedRegister> {
95 mmio: &'a mut M,
96 _phantom: PhantomData<R>,
97}
98
99impl<'a, M: Mmio + ?Sized, R: IndexedRegister> IndexedRegisterProxyMut<'a, M, R> {
100 pub fn new(mmio: &'a mut M) -> Self {
102 Self { mmio, _phantom: PhantomData }
103 }
104}
105
106impl<'a, M: Mmio + ?Sized, R: ReadableIndexedRegister> IndexedRegisterProxyMut<'a, M, R> {
107 pub fn read(&self, index: usize) -> R {
109 R::read_index(self.mmio, index)
110 }
111}
112
113impl<'a, M: Mmio + ?Sized, R: WritableIndexedRegister> IndexedRegisterProxyMut<'a, M, R> {
114 pub fn write(&mut self, index: usize, val: R) {
116 val.write_index(self.mmio, index)
117 }
118}
119
120impl<'a, M: Mmio + ?Sized, R: ReadableIndexedRegister + WritableIndexedRegister>
121 IndexedRegisterProxyMut<'a, M, R>
122{
123 pub fn update<F: FnOnce(&mut R)>(&mut self, index: usize, f: F) {
125 let mut reg = self.read(index);
126 f(&mut reg);
127 self.write(index, reg);
128 }
129}
130
131pub trait RegisterReadAccess<M: Mmio + ?Sized> {
133 type ReadProxy<'a>
135 where
136 M: 'a;
137
138 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a>;
140}
141
142pub trait RegisterWriteAccess<M: Mmio + ?Sized> {
144 type WriteProxy<'a>
146 where
147 M: 'a;
148
149 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a>;
151}
152
153pub trait Register: Sized {
159 type Value: MmioOperand;
161
162 const OFFSET: usize;
164
165 fn from_raw(value: Self::Value) -> Self;
167
168 fn to_raw(&self) -> Self::Value;
170}
171
172pub trait ReadableRegister: Register {
174 fn read<M: Mmio + ?Sized>(mmio: &M) -> Self {
176 Self::from_raw(mmio.load::<Self::Value>(Self::OFFSET))
177 }
178}
179
180pub trait WritableRegister: Register {
182 fn write<M: Mmio + ?Sized>(&self, mmio: &mut M) {
184 mmio.store::<Self::Value>(Self::OFFSET, self.to_raw())
185 }
186}
187
188pub trait IndexedRegister: Sized {
203 type Value: MmioOperand;
205
206 const BASE_OFFSET: usize;
208
209 const STRIDE: usize;
211
212 const COUNT: usize;
214
215 fn from_raw(value: Self::Value) -> Self;
217
218 fn to_raw(&self) -> Self::Value;
220}
221
222pub trait ReadableIndexedRegister: IndexedRegister {
224 fn read_index<M: Mmio + ?Sized>(mmio: &M, index: usize) -> Self {
232 assert!(index < Self::COUNT, "Register index out of bounds");
233 let offset = Self::BASE_OFFSET + (index * Self::STRIDE);
234 Self::from_raw(mmio.load::<Self::Value>(offset))
235 }
236}
237
238pub trait WritableIndexedRegister: IndexedRegister {
240 fn write_index<M: Mmio + ?Sized>(&self, mmio: &mut M, index: usize) {
248 assert!(index < Self::COUNT, "Register index out of bounds");
249 let offset = Self::BASE_OFFSET + (index * Self::STRIDE);
250 mmio.store::<Self::Value>(offset, self.to_raw())
251 }
252}
253
254#[macro_export]
288macro_rules! register {
289 ($(#[$attr:meta])* pub struct $name:ident ($val_type:ty) @ $offset:expr, RO { $($field_spec:tt)* }) => {
291 ::bitfield::bitfield! {
292 $(#[$attr])*
293 #[derive(Copy, Clone, PartialEq, Eq, Default)]
294 pub struct $name($val_type);
295 impl Debug;
296 $($field_spec)*
297 }
298
299 impl $crate::Register for $name {
300 type Value = $val_type;
301 const OFFSET: usize = $offset;
302 fn from_raw(value: Self::Value) -> Self { $name(value) }
303 fn to_raw(&self) -> Self::Value { self.0 }
304 }
305 impl $crate::ReadableRegister for $name {}
306
307 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
308 type ReadProxy<'a> = $crate::RegisterProxy<'a, M, $name> where M: 'a;
309 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> { $crate::RegisterProxy::new(mmio) }
310 }
311 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
312 type WriteProxy<'a> = $crate::RegisterProxyMut<'a, M, $name> where M: 'a;
313 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> { $crate::RegisterProxyMut::new(mmio) }
314 }
315 };
316
317 ($(#[$attr:meta])* pub struct $name:ident ($val_type:ty) @ $offset:expr, WO { $($field_spec:tt)* }) => {
319 ::bitfield::bitfield! {
320 $(#[$attr])*
321 #[derive(Copy, Clone, PartialEq, Eq, Default)]
322 pub struct $name($val_type);
323 impl Debug;
324 $($field_spec)*
325 }
326
327 impl $crate::Register for $name {
328 type Value = $val_type;
329 const OFFSET: usize = $offset;
330 fn from_raw(value: Self::Value) -> Self { $name(value) }
331 fn to_raw(&self) -> Self::Value { self.0 }
332 }
333 impl $crate::WritableRegister for $name {}
334
335 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
336 type ReadProxy<'a> = $crate::RegisterProxy<'a, M, $name> where M: 'a;
337 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> { $crate::RegisterProxy::new(mmio) }
338 }
339 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
340 type WriteProxy<'a> = $crate::RegisterProxyMut<'a, M, $name> where M: 'a;
341 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> { $crate::RegisterProxyMut::new(mmio) }
342 }
343 };
344
345 ($(#[$attr:meta])* pub struct $name:ident ($val_type:ty) @ $offset:expr, RW { $($field_spec:tt)* }) => {
347 ::bitfield::bitfield! {
348 $(#[$attr])*
349 #[derive(Copy, Clone, PartialEq, Eq, Default)]
350 pub struct $name($val_type);
351 impl Debug;
352 $($field_spec)*
353 }
354
355 impl $crate::Register for $name {
356 type Value = $val_type;
357 const OFFSET: usize = $offset;
358 fn from_raw(value: Self::Value) -> Self { $name(value) }
359 fn to_raw(&self) -> Self::Value { self.0 }
360 }
361 impl $crate::ReadableRegister for $name {}
362 impl $crate::WritableRegister for $name {}
363
364 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
365 type ReadProxy<'a> = $crate::RegisterProxy<'a, M, $name> where M: 'a;
366 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> { $crate::RegisterProxy::new(mmio) }
367 }
368 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
369 type WriteProxy<'a> = $crate::RegisterProxyMut<'a, M, $name> where M: 'a;
370 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> { $crate::RegisterProxyMut::new(mmio) }
371 }
372 };
373
374 ($(#[$attr:meta])* pub struct $name:ident ($val_type:ty) @ $offset:expr, RO ;) => {
376 ::bitfield::bitfield! {
377 $(#[$attr])*
378 #[derive(Copy, Clone, PartialEq, Eq, Default)]
379 pub struct $name($val_type);
380 impl Debug;
381 }
382
383 impl $name {
384 pub fn value(&self) -> $val_type { self.0 }
385 }
386
387 impl $crate::Register for $name {
388 type Value = $val_type;
389 const OFFSET: usize = $offset;
390 fn from_raw(value: Self::Value) -> Self { $name(value) }
391 fn to_raw(&self) -> Self::Value { self.0 }
392 }
393 impl $crate::ReadableRegister for $name {}
394
395 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
396 type ReadProxy<'a> = $crate::RegisterProxy<'a, M, $name> where M: 'a;
397 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> { $crate::RegisterProxy::new(mmio) }
398 }
399 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
400 type WriteProxy<'a> = $crate::RegisterProxyMut<'a, M, $name> where M: 'a;
401 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> { $crate::RegisterProxyMut::new(mmio) }
402 }
403 };
404
405 ($(#[$attr:meta])* pub struct $name:ident ($val_type:ty) @ $offset:expr, WO ;) => {
407 ::bitfield::bitfield! {
408 $(#[$attr])*
409 #[derive(Copy, Clone, PartialEq, Eq, Default)]
410 pub struct $name($val_type);
411 impl Debug;
412 }
413
414 impl $name {
415 pub fn set_value(&mut self, val: $val_type) { self.0 = val; }
416 }
417
418 impl $crate::Register for $name {
419 type Value = $val_type;
420 const OFFSET: usize = $offset;
421 fn from_raw(value: Self::Value) -> Self { $name(value) }
422 fn to_raw(&self) -> Self::Value { self.0 }
423 }
424 impl $crate::WritableRegister for $name {}
425
426 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
427 type ReadProxy<'a> = $crate::RegisterProxy<'a, M, $name> where M: 'a;
428 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> { $crate::RegisterProxy::new(mmio) }
429 }
430 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
431 type WriteProxy<'a> = $crate::RegisterProxyMut<'a, M, $name> where M: 'a;
432 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> { $crate::RegisterProxyMut::new(mmio) }
433 }
434 };
435
436 ($(#[$attr:meta])* pub struct $name:ident ($val_type:ty) @ $offset:expr, RW ;) => {
438 ::bitfield::bitfield! {
439 $(#[$attr])*
440 #[derive(Copy, Clone, PartialEq, Eq, Default)]
441 pub struct $name($val_type);
442 impl Debug;
443 }
444
445 impl $name {
446 pub fn value(&self) -> $val_type { self.0 }
447 pub fn set_value(&mut self, val: $val_type) { self.0 = val; }
448 }
449
450 impl $crate::Register for $name {
451 type Value = $val_type;
452 const OFFSET: usize = $offset;
453 fn from_raw(value: Self::Value) -> Self { $name(value) }
454 fn to_raw(&self) -> Self::Value { self.0 }
455 }
456 impl $crate::ReadableRegister for $name {}
457 impl $crate::WritableRegister for $name {}
458
459 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
460 type ReadProxy<'a> = $crate::RegisterProxy<'a, M, $name> where M: 'a;
461 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> { $crate::RegisterProxy::new(mmio) }
462 }
463 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
464 type WriteProxy<'a> = $crate::RegisterProxyMut<'a, M, $name> where M: 'a;
465 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> { $crate::RegisterProxyMut::new(mmio) }
466 }
467 };
468
469 ($name:ident, $val_type:ty, $offset:expr, RO, { $($field_spec:tt)* }) => {
471 ::bitfield::bitfield! {
472 #[derive(Copy, Clone, PartialEq, Eq, Default)]
473 pub struct $name($val_type);
474 impl Debug;
475 $($field_spec)*
476 }
477
478 impl $crate::Register for $name {
479 type Value = $val_type;
480 const OFFSET: usize = $offset;
481 fn from_raw(value: Self::Value) -> Self { $name(value) }
482 fn to_raw(&self) -> Self::Value { self.0 }
483 }
484 impl $crate::ReadableRegister for $name {}
485
486 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
487 type ReadProxy<'a> = $crate::RegisterProxy<'a, M, $name> where M: 'a;
488 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> { $crate::RegisterProxy::new(mmio) }
489 }
490 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
491 type WriteProxy<'a> = $crate::RegisterProxyMut<'a, M, $name> where M: 'a;
492 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> { $crate::RegisterProxyMut::new(mmio) }
493 }
494 };
495
496 ($name:ident, $val_type:ty, $offset:expr, WO, { $($field_spec:tt)* }) => {
498 ::bitfield::bitfield! {
499 #[derive(Copy, Clone, PartialEq, Eq, Default)]
500 pub struct $name($val_type);
501 impl Debug;
502 $($field_spec)*
503 }
504
505 impl $crate::Register for $name {
506 type Value = $val_type;
507 const OFFSET: usize = $offset;
508 fn from_raw(value: Self::Value) -> Self { $name(value) }
509 fn to_raw(&self) -> Self::Value { self.0 }
510 }
511 impl $crate::WritableRegister for $name {}
512
513 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
514 type ReadProxy<'a> = $crate::RegisterProxy<'a, M, $name> where M: 'a;
515 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> { $crate::RegisterProxy::new(mmio) }
516 }
517 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
518 type WriteProxy<'a> = $crate::RegisterProxyMut<'a, M, $name> where M: 'a;
519 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> { $crate::RegisterProxyMut::new(mmio) }
520 }
521 };
522
523 ($name:ident, $val_type:ty, $offset:expr, RW, { $($field_spec:tt)* }) => {
525 ::bitfield::bitfield! {
526 #[derive(Copy, Clone, PartialEq, Eq, Default)]
527 pub struct $name($val_type);
528 impl Debug;
529 $($field_spec)*
530 }
531
532 impl $crate::Register for $name {
533 type Value = $val_type;
534 const OFFSET: usize = $offset;
535 fn from_raw(value: Self::Value) -> Self { $name(value) }
536 fn to_raw(&self) -> Self::Value { self.0 }
537 }
538 impl $crate::ReadableRegister for $name {}
539 impl $crate::WritableRegister for $name {}
540
541 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
542 type ReadProxy<'a> = $crate::RegisterProxy<'a, M, $name> where M: 'a;
543 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> { $crate::RegisterProxy::new(mmio) }
544 }
545 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
546 type WriteProxy<'a> = $crate::RegisterProxyMut<'a, M, $name> where M: 'a;
547 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> { $crate::RegisterProxyMut::new(mmio) }
548 }
549 };
550}
551
552#[macro_export]
580macro_rules! indexed_register {
581 ($(#[$attr:meta])* pub struct $name:ident ($val_type:ty) @ $base_offset:expr, stride $stride:expr, count $count:expr, RO { $($field_spec:tt)* }) => {
583 ::bitfield::bitfield! {
584 $(#[$attr])*
585 #[derive(Copy, Clone, PartialEq, Eq, Default)]
586 pub struct $name($val_type);
587 impl Debug;
588 $($field_spec)*
589 }
590
591 impl $crate::IndexedRegister for $name {
592 type Value = $val_type;
593 const BASE_OFFSET: usize = $base_offset;
594 const STRIDE: usize = $stride;
595 const COUNT: usize = $count;
596 fn from_raw(value: Self::Value) -> Self { $name(value) }
597 fn to_raw(&self) -> Self::Value { self.0 }
598 }
599 impl $crate::ReadableIndexedRegister for $name {}
600
601 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
602 type ReadProxy<'a> = $crate::IndexedRegisterProxy<'a, M, $name> where M: 'a;
603 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> { $crate::IndexedRegisterProxy::new(mmio) }
604 }
605 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
606 type WriteProxy<'a> = $crate::IndexedRegisterProxyMut<'a, M, $name> where M: 'a;
607 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> { $crate::IndexedRegisterProxyMut::new(mmio) }
608 }
609 };
610
611 ($(#[$attr:meta])* pub struct $name:ident ($val_type:ty) @ $base_offset:expr, stride $stride:expr, count $count:expr, WO { $($field_spec:tt)* }) => {
613 ::bitfield::bitfield! {
614 $(#[$attr])*
615 #[derive(Copy, Clone, PartialEq, Eq, Default)]
616 pub struct $name($val_type);
617 impl Debug;
618 $($field_spec)*
619 }
620
621 impl $crate::IndexedRegister for $name {
622 type Value = $val_type;
623 const BASE_OFFSET: usize = $base_offset;
624 const STRIDE: usize = $stride;
625 const COUNT: usize = $count;
626 fn from_raw(value: Self::Value) -> Self { $name(value) }
627 fn to_raw(&self) -> Self::Value { self.0 }
628 }
629 impl $crate::WritableIndexedRegister for $name {}
630
631 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
632 type ReadProxy<'a> = $crate::IndexedRegisterProxy<'a, M, $name> where M: 'a;
633 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> { $crate::IndexedRegisterProxy::new(mmio) }
634 }
635 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
636 type WriteProxy<'a> = $crate::IndexedRegisterProxyMut<'a, M, $name> where M: 'a;
637 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> { $crate::IndexedRegisterProxyMut::new(mmio) }
638 }
639 };
640
641 ($(#[$attr:meta])* pub struct $name:ident ($val_type:ty) @ $base_offset:expr, stride $stride:expr, count $count:expr, RW { $($field_spec:tt)* }) => {
643 ::bitfield::bitfield! {
644 $(#[$attr])*
645 #[derive(Copy, Clone, PartialEq, Eq, Default)]
646 pub struct $name($val_type);
647 impl Debug;
648 $($field_spec)*
649 }
650
651 impl $crate::IndexedRegister for $name {
652 type Value = $val_type;
653 const BASE_OFFSET: usize = $base_offset;
654 const STRIDE: usize = $stride;
655 const COUNT: usize = $count;
656 fn from_raw(value: Self::Value) -> Self { $name(value) }
657 fn to_raw(&self) -> Self::Value { self.0 }
658 }
659 impl $crate::ReadableIndexedRegister for $name {}
660 impl $crate::WritableIndexedRegister for $name {}
661
662 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
663 type ReadProxy<'a> = $crate::IndexedRegisterProxy<'a, M, $name> where M: 'a;
664 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> { $crate::IndexedRegisterProxy::new(mmio) }
665 }
666 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
667 type WriteProxy<'a> = $crate::IndexedRegisterProxyMut<'a, M, $name> where M: 'a;
668 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> { $crate::IndexedRegisterProxyMut::new(mmio) }
669 }
670 };
671
672 ($(#[$attr:meta])* pub struct $name:ident ($val_type:ty) @ $base_offset:expr, stride $stride:expr, count $count:expr, RO ;) => {
674 ::bitfield::bitfield! {
675 $(#[$attr])*
676 #[derive(Copy, Clone, PartialEq, Eq, Default)]
677 pub struct $name($val_type);
678 impl Debug;
679 }
680
681 impl $name {
682 pub fn value(&self) -> $val_type { self.0 }
683 }
684
685 impl $crate::IndexedRegister for $name {
686 type Value = $val_type;
687 const BASE_OFFSET: usize = $base_offset;
688 const STRIDE: usize = $stride;
689 const COUNT: usize = $count;
690 fn from_raw(value: Self::Value) -> Self { $name(value) }
691 fn to_raw(&self) -> Self::Value { self.0 }
692 }
693 impl $crate::ReadableIndexedRegister for $name {}
694
695 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
696 type ReadProxy<'a> = $crate::IndexedRegisterProxy<'a, M, $name> where M: 'a;
697 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> { $crate::IndexedRegisterProxy::new(mmio) }
698 }
699 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
700 type WriteProxy<'a> = $crate::IndexedRegisterProxyMut<'a, M, $name> where M: 'a;
701 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> { $crate::IndexedRegisterProxyMut::new(mmio) }
702 }
703 };
704
705 ($(#[$attr:meta])* pub struct $name:ident ($val_type:ty) @ $base_offset:expr, stride $stride:expr, count $count:expr, WO ;) => {
707 ::bitfield::bitfield! {
708 $(#[$attr])*
709 #[derive(Copy, Clone, PartialEq, Eq, Default)]
710 pub struct $name($val_type);
711 impl Debug;
712 }
713
714 impl $name {
715 pub fn set_value(&mut self, val: $val_type) { self.0 = val; }
716 }
717
718 impl $crate::IndexedRegister for $name {
719 type Value = $val_type;
720 const BASE_OFFSET: usize = $base_offset;
721 const STRIDE: usize = $stride;
722 const COUNT: usize = $count;
723 fn from_raw(value: Self::Value) -> Self { $name(value) }
724 fn to_raw(&self) -> Self::Value { self.0 }
725 }
726 impl $crate::WritableIndexedRegister for $name {}
727
728 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
729 type ReadProxy<'a> = $crate::IndexedRegisterProxy<'a, M, $name> where M: 'a;
730 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> { $crate::IndexedRegisterProxy::new(mmio) }
731 }
732 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
733 type WriteProxy<'a> = $crate::IndexedRegisterProxyMut<'a, M, $name> where M: 'a;
734 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> { $crate::IndexedRegisterProxyMut::new(mmio) }
735 }
736 };
737
738 ($(#[$attr:meta])* pub struct $name:ident ($val_type:ty) @ $base_offset:expr, stride $stride:expr, count $count:expr, RW ;) => {
740 ::bitfield::bitfield! {
741 $(#[$attr])*
742 #[derive(Copy, Clone, PartialEq, Eq, Default)]
743 pub struct $name($val_type);
744 impl Debug;
745 }
746
747 impl $name {
748 pub fn value(&self) -> $val_type { self.0 }
749 pub fn set_value(&mut self, val: $val_type) { self.0 = val; }
750 }
751
752 impl $crate::IndexedRegister for $name {
753 type Value = $val_type;
754 const BASE_OFFSET: usize = $base_offset;
755 const STRIDE: usize = $stride;
756 const COUNT: usize = $count;
757 fn from_raw(value: Self::Value) -> Self { $name(value) }
758 fn to_raw(&self) -> Self::Value { self.0 }
759 }
760 impl $crate::ReadableIndexedRegister for $name {}
761 impl $crate::WritableIndexedRegister for $name {}
762
763 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
764 type ReadProxy<'a> = $crate::IndexedRegisterProxy<'a, M, $name> where M: 'a;
765 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> { $crate::IndexedRegisterProxy::new(mmio) }
766 }
767 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
768 type WriteProxy<'a> = $crate::IndexedRegisterProxyMut<'a, M, $name> where M: 'a;
769 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> { $crate::IndexedRegisterProxyMut::new(mmio) }
770 }
771 };
772
773 ($name:ident, $val_type:ty, $base_offset:expr, $stride:expr, $count:expr, RO, { $($field_spec:tt)* }) => {
775 ::bitfield::bitfield! {
776 #[derive(Copy, Clone, PartialEq, Eq, Default)]
777 pub struct $name($val_type);
778 impl Debug;
779 $($field_spec)*
780 }
781
782 impl $crate::IndexedRegister for $name {
783 type Value = $val_type;
784 const BASE_OFFSET: usize = $base_offset;
785 const STRIDE: usize = $stride;
786 const COUNT: usize = $count;
787 fn from_raw(value: Self::Value) -> Self { $name(value) }
788 fn to_raw(&self) -> Self::Value { self.0 }
789 }
790 impl $crate::ReadableIndexedRegister for $name {}
791
792 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
793 type ReadProxy<'a> = $crate::IndexedRegisterProxy<'a, M, $name> where M: 'a;
794 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> { $crate::IndexedRegisterProxy::new(mmio) }
795 }
796 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
797 type WriteProxy<'a> = $crate::IndexedRegisterProxyMut<'a, M, $name> where M: 'a;
798 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> { $crate::IndexedRegisterProxyMut::new(mmio) }
799 }
800 };
801
802 ($name:ident, $val_type:ty, $base_offset:expr, $stride:expr, $count:expr, WO, { $($field_spec:tt)* }) => {
804 ::bitfield::bitfield! {
805 #[derive(Copy, Clone, PartialEq, Eq, Default)]
806 pub struct $name($val_type);
807 impl Debug;
808 $($field_spec)*
809 }
810
811 impl $crate::IndexedRegister for $name {
812 type Value = $val_type;
813 const BASE_OFFSET: usize = $base_offset;
814 const STRIDE: usize = $stride;
815 const COUNT: usize = $count;
816 fn from_raw(value: Self::Value) -> Self { $name(value) }
817 fn to_raw(&self) -> Self::Value { self.0 }
818 }
819 impl $crate::WritableIndexedRegister for $name {}
820
821 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
822 type ReadProxy<'a> = $crate::IndexedRegisterProxy<'a, M, $name> where M: 'a;
823 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> { $crate::IndexedRegisterProxy::new(mmio) }
824 }
825 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
826 type WriteProxy<'a> = $crate::IndexedRegisterProxyMut<'a, M, $name> where M: 'a;
827 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> { $crate::IndexedRegisterProxyMut::new(mmio) }
828 }
829 };
830
831 ($name:ident, $val_type:ty, $base_offset:expr, $stride:expr, $count:expr, RW, { $($field_spec:tt)* }) => {
833 ::bitfield::bitfield! {
834 #[derive(Copy, Clone, PartialEq, Eq, Default)]
835 pub struct $name($val_type);
836 impl Debug;
837 $($field_spec)*
838 }
839
840 impl $crate::IndexedRegister for $name {
841 type Value = $val_type;
842 const BASE_OFFSET: usize = $base_offset;
843 const STRIDE: usize = $stride;
844 const COUNT: usize = $count;
845 fn from_raw(value: Self::Value) -> Self { $name(value) }
846 fn to_raw(&self) -> Self::Value { self.0 }
847 }
848 impl $crate::ReadableIndexedRegister for $name {}
849 impl $crate::WritableIndexedRegister for $name {}
850
851 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
852 type ReadProxy<'a> = $crate::IndexedRegisterProxy<'a, M, $name> where M: 'a;
853 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> { $crate::IndexedRegisterProxy::new(mmio) }
854 }
855 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
856 type WriteProxy<'a> = $crate::IndexedRegisterProxyMut<'a, M, $name> where M: 'a;
857 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> { $crate::IndexedRegisterProxyMut::new(mmio) }
858 }
859 };
860}
861
862#[macro_export]
887macro_rules! register_block {
888 (
889 $vis:vis struct $name:ident <$mmio:ident> {
890 $(
891 $(#[$attr:meta])*
892 $field_vis:vis $field:ident : $reg_type:ident
893 ),* $(,)?
894 }
895 ) => {
896 $vis struct $name<$mmio> {
897 pub mmio: $mmio,
898 }
899
900 impl<$mmio: $crate::Mmio> $name<$mmio> {
901 pub fn new(mmio: $mmio) -> Self {
903 Self { mmio }
904 }
905
906 $(
907 $(#[$attr])*
908 $crate::paste::paste! {
909 #[allow(dead_code)]
910 $field_vis fn $field(&self) -> <$reg_type as $crate::RegisterReadAccess<$mmio>>::ReadProxy<'_> {
911 <$reg_type as $crate::RegisterReadAccess<$mmio>>::get_read_proxy(&self.mmio)
912 }
913
914 $(#[$attr])*
915 #[allow(dead_code)]
916 $field_vis fn [<$field _mut>](&mut self) -> <$reg_type as $crate::RegisterWriteAccess<$mmio>>::WriteProxy<'_> {
917 <$reg_type as $crate::RegisterWriteAccess<$mmio>>::get_write_proxy(&mut self.mmio)
918 }
919 }
920 )*
921 }
922 };
923}
924
925#[cfg(test)]
926mod tests {
927 use super::*;
928 use crate::memory::Memory;
929 use core::mem::MaybeUninit;
930
931 register! {
932 TestReg, u32, 4, RW, {
933 pub field1, set_field1: 7, 0;
934 pub field2, set_field2: 15, 8;
935 }
936 }
937
938 register! {
939 ReadOnlyReg, u32, 8, RO, {
940 pub field1, _: 7, 0;
941 }
942 }
943
944 register! {
945 WriteOnlyReg, u32, 12, WO, {
946 _, set_field1: 7, 0;
947 }
948 }
949
950 indexed_register! {
951 TestIndexedReg, u32, 16, 4, 2, RW, {
952 pub field1, set_field1: 7, 0;
953 }
954 }
955
956 register_block! {
957 pub struct TestBlock<M> {
958 pub test_reg: TestReg,
959 pub ro_reg: ReadOnlyReg,
960 pub wo_reg: WriteOnlyReg,
961 pub indexed: TestIndexedReg,
962 }
963 }
964
965 #[test]
966 fn test_register_read_write() {
967 let mut mem = MaybeUninit::<[u32; 8]>::zeroed();
968 let mut mmio = Memory::borrow_uninit(&mut mem);
969
970 let mut reg = TestReg::default();
971 reg.set_field1(0x12);
972 reg.set_field2(0x34);
973
974 reg.write(&mut mmio);
975
976 let reg2 = TestReg::read(&mmio);
977 assert_eq!(reg, reg2);
978 assert_eq!(reg2.field1(), 0x12);
979 assert_eq!(reg2.field2(), 0x34);
980 }
981
982 #[test]
983 fn test_update_reg() {
984 let mut mem = MaybeUninit::<[u32; 8]>::zeroed();
985 let mut mmio = Memory::borrow_uninit(&mut mem);
986
987 mmio.update_reg::<TestReg, _>(|reg| {
988 reg.set_field1(0xab);
989 });
990
991 let reg = mmio.read_reg::<TestReg>();
992 assert_eq!(reg.field1(), 0xab);
993 assert_eq!(reg.field2(), 0);
994 }
995
996 #[test]
997 fn test_register_proxy() {
998 let mut mem = MaybeUninit::<[u32; 8]>::zeroed();
999 let mut mmio = Memory::borrow_uninit(&mut mem);
1000
1001 mmio.store32(4, 0x1234);
1003 let proxy = mmio.reg::<TestReg>();
1004 assert_eq!(proxy.read().field1(), 0x34);
1005
1006 {
1008 let mut proxy_mut = mmio.reg_mut::<TestReg>();
1009 proxy_mut.update(|reg| {
1010 reg.set_field1(0x56);
1011 });
1012 assert_eq!(proxy_mut.read().field1(), 0x56);
1013
1014 proxy_mut.write(TestReg(0x78));
1015 }
1016 assert_eq!(mmio.load32(4), 0x78);
1017 }
1018
1019 #[test]
1020 fn test_indexed_register() {
1021 let mut mem = MaybeUninit::<[u32; 12]>::zeroed();
1022 let mut mmio = Memory::borrow_uninit(&mut mem);
1023
1024 let mut reg = TestIndexedReg::default();
1025 reg.set_field1(0x11);
1026 reg.write_index(&mut mmio, 0);
1027
1028 reg.set_field1(0x22);
1029 reg.write_index(&mut mmio, 1);
1030
1031 assert_eq!(mmio.load32(16), 0x11);
1032 assert_eq!(mmio.load32(20), 0x22);
1033
1034 let reg0 = TestIndexedReg::read_index(&mmio, 0);
1035 assert_eq!(reg0.field1(), 0x11);
1036
1037 let reg1 = TestIndexedReg::read_index(&mmio, 1);
1038 assert_eq!(reg1.field1(), 0x22);
1039 }
1040
1041 #[test]
1042 fn test_indexed_register_proxy() {
1043 let mut mem = MaybeUninit::<[u32; 12]>::zeroed();
1044 let mut mmio = Memory::borrow_uninit(&mut mem);
1045
1046 {
1047 let mut proxy = mmio.indexed_reg_mut::<TestIndexedReg>();
1048 proxy.write(0, TestIndexedReg(0xaa));
1049 proxy.update(1, |reg| reg.set_field1(0xbb));
1050
1051 assert_eq!(proxy.read(0).field1(), 0xaa);
1052 assert_eq!(proxy.read(1).field1(), 0xbb);
1053 }
1054
1055 assert_eq!(mmio.load32(16), 0xaa);
1056 assert_eq!(mmio.load32(20), 0xbb);
1057 }
1058
1059 #[test]
1060 #[should_panic(expected = "Register index out of bounds")]
1061 fn test_indexed_register_out_of_bounds_read() {
1062 let mut mem = MaybeUninit::<[u32; 12]>::zeroed();
1063 let mmio = Memory::borrow_uninit(&mut mem);
1064 let _ = TestIndexedReg::read_index(&mmio, 2);
1065 }
1066
1067 #[test]
1068 #[should_panic(expected = "Register index out of bounds")]
1069 fn test_indexed_register_out_of_bounds_write() {
1070 let mut mem = MaybeUninit::<[u32; 12]>::zeroed();
1071 let mut mmio = Memory::borrow_uninit(&mut mem);
1072 let reg = TestIndexedReg::default();
1073 reg.write_index(&mut mmio, 2);
1074 }
1075
1076 #[test]
1077 fn test_register_block() {
1078 let mut mem = MaybeUninit::<[u32; 12]>::zeroed();
1079 let mmio = Memory::borrow_uninit(&mut mem);
1080 let mut block = TestBlock::new(mmio);
1081
1082 block.test_reg_mut().write(TestReg(0x1234));
1083 assert_eq!(block.mmio.load32(4), 0x1234);
1084
1085 block.mmio.store32(8, 0xabcd);
1086 assert_eq!(block.ro_reg().read().field1(), 0xcd);
1087
1088 block.wo_reg_mut().write(WriteOnlyReg(0x55));
1089 assert_eq!(block.mmio.load32(12), 0x55);
1090
1091 block.indexed_mut().write(0, TestIndexedReg(0x11));
1092 block.indexed_mut().write(1, TestIndexedReg(0x22));
1093 assert_eq!(block.mmio.load32(16), 0x11);
1094 assert_eq!(block.mmio.load32(20), 0x22);
1095
1096 let block = block;
1098 assert_eq!(block.test_reg().read().field1(), 0x34);
1099 assert_eq!(block.ro_reg().read().field1(), 0xcd);
1100 assert_eq!(block.indexed().read(0).field1(), 0x11);
1101 }
1102
1103 register! {
1104 pub struct NewSyntaxReg(u32) @ 4, RW {
1106 pub field1, set_field1: 7, 0;
1107 }
1108 }
1109
1110 register! {
1111 pub struct FullWidthReg(u32) @ 8, RW;
1113 }
1114
1115 indexed_register! {
1116 pub struct NewSyntaxIndexedReg(u32) @ 12, stride 4, count 2, RW {
1118 pub field1, set_field1: 7, 0;
1119 }
1120 }
1121
1122 #[test]
1123 fn test_new_syntax() {
1124 let mut mem = MaybeUninit::<[u32; 8]>::zeroed();
1125 let mut mmio = Memory::borrow_uninit(&mut mem);
1126
1127 let mut reg = NewSyntaxReg::default();
1128 reg.set_field1(0x55);
1129 reg.write(&mut mmio);
1130
1131 let reg2 = NewSyntaxReg::read(&mmio);
1132 assert_eq!(reg2.field1(), 0x55);
1133 }
1134
1135 #[test]
1136 fn test_full_width() {
1137 let mut mem = MaybeUninit::<[u32; 8]>::zeroed();
1138 let mut mmio = Memory::borrow_uninit(&mut mem);
1139
1140 let mut reg = FullWidthReg::default();
1141 reg.set_value(0x12345678);
1142 reg.write(&mut mmio);
1143
1144 let reg2 = FullWidthReg::read(&mmio);
1145 assert_eq!(reg2.value(), 0x12345678);
1146 }
1147
1148 #[test]
1149 fn test_new_syntax_indexed() {
1150 let mut mem = MaybeUninit::<[u32; 8]>::zeroed();
1151 let mut mmio = Memory::borrow_uninit(&mut mem);
1152
1153 let mut reg = NewSyntaxIndexedReg::default();
1154 reg.set_field1(0xaa);
1155 reg.write_index(&mut mmio, 0);
1156
1157 reg.set_field1(0xbb);
1158 reg.write_index(&mut mmio, 1);
1159
1160 let reg0 = NewSyntaxIndexedReg::read_index(&mmio, 0);
1161 assert_eq!(reg0.field1(), 0xaa);
1162
1163 let reg1 = NewSyntaxIndexedReg::read_index(&mmio, 1);
1164 assert_eq!(reg1.field1(), 0xbb);
1165 }
1166}