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]
280macro_rules! register {
281 ($name:ident, $val_type:ty, $offset:expr, RO, { $($field_spec:tt)* }) => {
282 ::bitfield::bitfield! {
283 #[derive(Copy, Clone, PartialEq, Eq, Default)]
284 pub struct $name($val_type);
285 impl Debug;
286 $($field_spec)*
287 }
288
289 impl $crate::Register for $name {
290 type Value = $val_type;
291 const OFFSET: usize = $offset;
292
293 fn from_raw(value: Self::Value) -> Self {
294 $name(value)
295 }
296
297 fn to_raw(&self) -> Self::Value {
298 self.0
299 }
300 }
301
302 impl $crate::ReadableRegister for $name {}
303
304 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
305 type ReadProxy<'a> = $crate::RegisterProxy<'a, M, $name> where M: 'a;
306 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> {
307 $crate::RegisterProxy::new(mmio)
308 }
309 }
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> {
314 $crate::RegisterProxyMut::new(mmio)
315 }
316 }
317 };
318 ($name:ident, $val_type:ty, $offset:expr, WO, { $($field_spec:tt)* }) => {
319 ::bitfield::bitfield! {
320 #[derive(Copy, Clone, PartialEq, Eq, Default)]
321 pub struct $name($val_type);
322 impl Debug;
323 $($field_spec)*
324 }
325
326 impl $crate::Register for $name {
327 type Value = $val_type;
328 const OFFSET: usize = $offset;
329
330 fn from_raw(value: Self::Value) -> Self {
331 $name(value)
332 }
333
334 fn to_raw(&self) -> Self::Value {
335 self.0
336 }
337 }
338
339 impl $crate::WritableRegister for $name {}
340
341 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
342 type ReadProxy<'a> = $crate::RegisterProxy<'a, M, $name> where M: 'a;
343 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> {
344 $crate::RegisterProxy::new(mmio)
345 }
346 }
347
348 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
349 type WriteProxy<'a> = $crate::RegisterProxyMut<'a, M, $name> where M: 'a;
350 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> {
351 $crate::RegisterProxyMut::new(mmio)
352 }
353 }
354 };
355 ($name:ident, $val_type:ty, $offset:expr, RW, { $($field_spec:tt)* }) => {
356 ::bitfield::bitfield! {
357 #[derive(Copy, Clone, PartialEq, Eq, Default)]
358 pub struct $name($val_type);
359 impl Debug;
360 $($field_spec)*
361 }
362
363 impl $crate::Register for $name {
364 type Value = $val_type;
365 const OFFSET: usize = $offset;
366
367 fn from_raw(value: Self::Value) -> Self {
368 $name(value)
369 }
370
371 fn to_raw(&self) -> Self::Value {
372 self.0
373 }
374 }
375
376 impl $crate::ReadableRegister for $name {}
377 impl $crate::WritableRegister for $name {}
378
379 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
380 type ReadProxy<'a> = $crate::RegisterProxy<'a, M, $name> where M: 'a;
381 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> {
382 $crate::RegisterProxy::new(mmio)
383 }
384 }
385
386 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
387 type WriteProxy<'a> = $crate::RegisterProxyMut<'a, M, $name> where M: 'a;
388 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> {
389 $crate::RegisterProxyMut::new(mmio)
390 }
391 }
392 };
393}
394
395#[macro_export]
415macro_rules! indexed_register {
416 ($name:ident, $val_type:ty, $base_offset:expr, $stride:expr, $count:expr, RO, { $($field_spec:tt)* }) => {
417 ::bitfield::bitfield! {
418 #[derive(Copy, Clone, PartialEq, Eq, Default)]
419 pub struct $name($val_type);
420 impl Debug;
421 $($field_spec)*
422 }
423
424 impl $crate::IndexedRegister for $name {
425 type Value = $val_type;
426 const BASE_OFFSET: usize = $base_offset;
427 const STRIDE: usize = $stride;
428 const COUNT: usize = $count;
429
430 fn from_raw(value: Self::Value) -> Self {
431 $name(value)
432 }
433
434 fn to_raw(&self) -> Self::Value {
435 self.0
436 }
437 }
438
439 impl $crate::ReadableIndexedRegister for $name {}
440
441 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
442 type ReadProxy<'a> = $crate::IndexedRegisterProxy<'a, M, $name> where M: 'a;
443 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> {
444 $crate::IndexedRegisterProxy::new(mmio)
445 }
446 }
447
448 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
449 type WriteProxy<'a> = $crate::IndexedRegisterProxyMut<'a, M, $name> where M: 'a;
450 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> {
451 $crate::IndexedRegisterProxyMut::new(mmio)
452 }
453 }
454 };
455 ($name:ident, $val_type:ty, $base_offset:expr, $stride:expr, $count:expr, WO, { $($field_spec:tt)* }) => {
456 ::bitfield::bitfield! {
457 #[derive(Copy, Clone, PartialEq, Eq, Default)]
458 pub struct $name($val_type);
459 impl Debug;
460 $($field_spec)*
461 }
462
463 impl $crate::IndexedRegister for $name {
464 type Value = $val_type;
465 const BASE_OFFSET: usize = $base_offset;
466 const STRIDE: usize = $stride;
467 const COUNT: usize = $count;
468
469 fn from_raw(value: Self::Value) -> Self {
470 $name(value)
471 }
472
473 fn to_raw(&self) -> Self::Value {
474 self.0
475 }
476 }
477
478 impl $crate::WritableIndexedRegister for $name {}
479
480 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
481 type ReadProxy<'a> = $crate::IndexedRegisterProxy<'a, M, $name> where M: 'a;
482 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> {
483 $crate::IndexedRegisterProxy::new(mmio)
484 }
485 }
486
487 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
488 type WriteProxy<'a> = $crate::IndexedRegisterProxyMut<'a, M, $name> where M: 'a;
489 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> {
490 $crate::IndexedRegisterProxyMut::new(mmio)
491 }
492 }
493 };
494 ($name:ident, $val_type:ty, $base_offset:expr, $stride:expr, $count:expr, RW, { $($field_spec:tt)* }) => {
495 ::bitfield::bitfield! {
496 #[derive(Copy, Clone, PartialEq, Eq, Default)]
497 pub struct $name($val_type);
498 impl Debug;
499 $($field_spec)*
500 }
501
502 impl $crate::IndexedRegister for $name {
503 type Value = $val_type;
504 const BASE_OFFSET: usize = $base_offset;
505 const STRIDE: usize = $stride;
506 const COUNT: usize = $count;
507
508 fn from_raw(value: Self::Value) -> Self {
509 $name(value)
510 }
511
512 fn to_raw(&self) -> Self::Value {
513 self.0
514 }
515 }
516
517 impl $crate::ReadableIndexedRegister for $name {}
518 impl $crate::WritableIndexedRegister for $name {}
519
520 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
521 type ReadProxy<'a> = $crate::IndexedRegisterProxy<'a, M, $name> where M: 'a;
522 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> {
523 $crate::IndexedRegisterProxy::new(mmio)
524 }
525 }
526
527 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
528 type WriteProxy<'a> = $crate::IndexedRegisterProxyMut<'a, M, $name> where M: 'a;
529 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> {
530 $crate::IndexedRegisterProxyMut::new(mmio)
531 }
532 }
533 };
534}
535
536#[macro_export]
561macro_rules! register_block {
562 (
563 $vis:vis struct $name:ident <$mmio:ident> {
564 $(
565 $(#[$attr:meta])*
566 $field_vis:vis $field:ident : $reg_type:ident
567 ),* $(,)?
568 }
569 ) => {
570 $vis struct $name<$mmio> {
571 pub mmio: $mmio,
572 }
573
574 impl<$mmio: $crate::Mmio> $name<$mmio> {
575 pub fn new(mmio: $mmio) -> Self {
577 Self { mmio }
578 }
579
580 $(
581 $(#[$attr])*
582 $crate::paste::paste! {
583 #[allow(dead_code)]
584 $field_vis fn $field(&self) -> <$reg_type as $crate::RegisterReadAccess<$mmio>>::ReadProxy<'_> {
585 <$reg_type as $crate::RegisterReadAccess<$mmio>>::get_read_proxy(&self.mmio)
586 }
587
588 $(#[$attr])*
589 #[allow(dead_code)]
590 $field_vis fn [<$field _mut>](&mut self) -> <$reg_type as $crate::RegisterWriteAccess<$mmio>>::WriteProxy<'_> {
591 <$reg_type as $crate::RegisterWriteAccess<$mmio>>::get_write_proxy(&mut self.mmio)
592 }
593 }
594 )*
595 }
596 };
597}
598
599#[cfg(test)]
600mod tests {
601 use super::*;
602 use crate::memory::Memory;
603 use core::mem::MaybeUninit;
604
605 register! {
606 TestReg, u32, 4, RW, {
607 pub field1, set_field1: 7, 0;
608 pub field2, set_field2: 15, 8;
609 }
610 }
611
612 register! {
613 ReadOnlyReg, u32, 8, RO, {
614 pub field1, _: 7, 0;
615 }
616 }
617
618 register! {
619 WriteOnlyReg, u32, 12, WO, {
620 _, set_field1: 7, 0;
621 }
622 }
623
624 indexed_register! {
625 TestIndexedReg, u32, 16, 4, 2, RW, {
626 pub field1, set_field1: 7, 0;
627 }
628 }
629
630 register_block! {
631 pub struct TestBlock<M> {
632 pub test_reg: TestReg,
633 pub ro_reg: ReadOnlyReg,
634 pub wo_reg: WriteOnlyReg,
635 pub indexed: TestIndexedReg,
636 }
637 }
638
639 #[test]
640 fn test_register_read_write() {
641 let mut mem = MaybeUninit::<[u32; 8]>::zeroed();
642 let mut mmio = Memory::borrow_uninit(&mut mem);
643
644 let mut reg = TestReg::default();
645 reg.set_field1(0x12);
646 reg.set_field2(0x34);
647
648 reg.write(&mut mmio);
649
650 let reg2 = TestReg::read(&mmio);
651 assert_eq!(reg, reg2);
652 assert_eq!(reg2.field1(), 0x12);
653 assert_eq!(reg2.field2(), 0x34);
654 }
655
656 #[test]
657 fn test_update_reg() {
658 let mut mem = MaybeUninit::<[u32; 8]>::zeroed();
659 let mut mmio = Memory::borrow_uninit(&mut mem);
660
661 mmio.update_reg::<TestReg, _>(|reg| {
662 reg.set_field1(0xab);
663 });
664
665 let reg = mmio.read_reg::<TestReg>();
666 assert_eq!(reg.field1(), 0xab);
667 assert_eq!(reg.field2(), 0);
668 }
669
670 #[test]
671 fn test_register_proxy() {
672 let mut mem = MaybeUninit::<[u32; 8]>::zeroed();
673 let mut mmio = Memory::borrow_uninit(&mut mem);
674
675 mmio.store32(4, 0x1234);
677 let proxy = mmio.reg::<TestReg>();
678 assert_eq!(proxy.read().field1(), 0x34);
679
680 {
682 let mut proxy_mut = mmio.reg_mut::<TestReg>();
683 proxy_mut.update(|reg| {
684 reg.set_field1(0x56);
685 });
686 assert_eq!(proxy_mut.read().field1(), 0x56);
687
688 proxy_mut.write(TestReg(0x78));
689 }
690 assert_eq!(mmio.load32(4), 0x78);
691 }
692
693 #[test]
694 fn test_indexed_register() {
695 let mut mem = MaybeUninit::<[u32; 12]>::zeroed();
696 let mut mmio = Memory::borrow_uninit(&mut mem);
697
698 let mut reg = TestIndexedReg::default();
699 reg.set_field1(0x11);
700 reg.write_index(&mut mmio, 0);
701
702 reg.set_field1(0x22);
703 reg.write_index(&mut mmio, 1);
704
705 assert_eq!(mmio.load32(16), 0x11);
706 assert_eq!(mmio.load32(20), 0x22);
707
708 let reg0 = TestIndexedReg::read_index(&mmio, 0);
709 assert_eq!(reg0.field1(), 0x11);
710
711 let reg1 = TestIndexedReg::read_index(&mmio, 1);
712 assert_eq!(reg1.field1(), 0x22);
713 }
714
715 #[test]
716 fn test_indexed_register_proxy() {
717 let mut mem = MaybeUninit::<[u32; 12]>::zeroed();
718 let mut mmio = Memory::borrow_uninit(&mut mem);
719
720 {
721 let mut proxy = mmio.indexed_reg_mut::<TestIndexedReg>();
722 proxy.write(0, TestIndexedReg(0xaa));
723 proxy.update(1, |reg| reg.set_field1(0xbb));
724
725 assert_eq!(proxy.read(0).field1(), 0xaa);
726 assert_eq!(proxy.read(1).field1(), 0xbb);
727 }
728
729 assert_eq!(mmio.load32(16), 0xaa);
730 assert_eq!(mmio.load32(20), 0xbb);
731 }
732
733 #[test]
734 #[should_panic(expected = "Register index out of bounds")]
735 fn test_indexed_register_out_of_bounds_read() {
736 let mut mem = MaybeUninit::<[u32; 12]>::zeroed();
737 let mmio = Memory::borrow_uninit(&mut mem);
738 let _ = TestIndexedReg::read_index(&mmio, 2);
739 }
740
741 #[test]
742 #[should_panic(expected = "Register index out of bounds")]
743 fn test_indexed_register_out_of_bounds_write() {
744 let mut mem = MaybeUninit::<[u32; 12]>::zeroed();
745 let mut mmio = Memory::borrow_uninit(&mut mem);
746 let reg = TestIndexedReg::default();
747 reg.write_index(&mut mmio, 2);
748 }
749
750 #[test]
751 fn test_register_block() {
752 let mut mem = MaybeUninit::<[u32; 12]>::zeroed();
753 let mmio = Memory::borrow_uninit(&mut mem);
754 let mut block = TestBlock::new(mmio);
755
756 block.test_reg_mut().write(TestReg(0x1234));
757 assert_eq!(block.mmio.load32(4), 0x1234);
758
759 block.mmio.store32(8, 0xabcd);
760 assert_eq!(block.ro_reg().read().field1(), 0xcd);
761
762 block.wo_reg_mut().write(WriteOnlyReg(0x55));
763 assert_eq!(block.mmio.load32(12), 0x55);
764
765 block.indexed_mut().write(0, TestIndexedReg(0x11));
766 block.indexed_mut().write(1, TestIndexedReg(0x22));
767 assert_eq!(block.mmio.load32(16), 0x11);
768 assert_eq!(block.mmio.load32(20), 0x22);
769
770 let block = block;
772 assert_eq!(block.test_reg().read().field1(), 0x34);
773 assert_eq!(block.ro_reg().read().field1(), 0xcd);
774 assert_eq!(block.indexed().read(0).field1(), 0x11);
775 }
776}