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