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 {
204 type Value: MmioOperand;
206
207 const BASE_OFFSET: usize;
209
210 const STRIDE: usize;
212
213 const COUNT: usize;
215
216 fn from_raw(value: Self::Value) -> Self;
218
219 fn to_raw(&self) -> Self::Value;
221}
222
223pub trait ReadableIndexedRegister: IndexedRegister {
225 fn read_index<M: Mmio + ?Sized>(mmio: &M, index: usize) -> Self {
233 assert!(index < Self::COUNT, "Register index out of bounds");
234 let offset = Self::BASE_OFFSET + (index * Self::STRIDE);
235 Self::from_raw(mmio.load::<Self::Value>(offset))
236 }
237}
238
239pub trait WritableIndexedRegister: IndexedRegister {
241 fn write_index<M: Mmio + ?Sized>(&self, mmio: &mut M, index: usize) {
249 assert!(index < Self::COUNT, "Register index out of bounds");
250 let offset = Self::BASE_OFFSET + (index * Self::STRIDE);
251 mmio.store::<Self::Value>(offset, self.to_raw())
252 }
253}
254
255#[macro_export]
312macro_rules! register {
313 (
315 #[register(offset = $offset:expr, mode = $mode:ident)]
316 $(#[$attr:meta])*
317 pub struct $name:ident ($val_type:ty) { $($field_spec:tt)* }
318 $($tail:tt)+
319 ) => {
320 $crate::register! { #[register(offset = $offset, mode = $mode)] $(#[$attr])* pub struct $name($val_type) { $($field_spec)* } }
321 $crate::register! { $($tail)+ }
322 };
323
324 (
326 #[register(offset = $offset:expr, mode = $mode:ident)]
327 $(#[$attr:meta])*
328 pub struct $name:ident ($val_type:ty) ;
329 $($tail:tt)+
330 ) => {
331 $crate::register! { #[register(offset = $offset, mode = $mode)] $(#[$attr])* pub struct $name($val_type) ; }
332 $crate::register! { $($tail)+ }
333 };
334
335 (
337 #[indexed_register(offset = $base_offset:expr, stride = $stride:expr, count = $count:expr, mode = $mode:ident)]
338 $(#[$attr:meta])*
339 pub struct $name:ident ($val_type:ty) { $($field_spec:tt)* }
340 $($tail:tt)+
341 ) => {
342 $crate::register! { #[indexed_register(offset = $base_offset, stride = $stride, count = $count, mode = $mode)] $(#[$attr])* pub struct $name($val_type) { $($field_spec)* } }
343 $crate::register! { $($tail)+ }
344 };
345
346 (
348 #[indexed_register(offset = $base_offset:expr, stride = $stride:expr, count = $count:expr, mode = $mode:ident)]
349 $(#[$attr:meta])*
350 pub struct $name:ident ($val_type:ty) ;
351 $($tail:tt)+
352 ) => {
353 $crate::register! { #[indexed_register(offset = $base_offset, stride = $stride, count = $count, mode = $mode)] $(#[$attr])* pub struct $name($val_type) ; }
354 $crate::register! { $($tail)+ }
355 };
356
357 (
359 #[register(offset = $offset:expr, mode = RO)]
360 $(#[$attr:meta])*
361 pub struct $name:ident ($val_type:ty) { $($field_spec:tt)* }
362 ) => {
363 ::bitfield::bitfield! {
364 $(#[$attr])*
365 #[derive(Copy, Clone, PartialEq, Eq, Default)]
366 pub struct $name($val_type);
367 impl Debug;
368 $($field_spec)*
369 }
370
371 impl $crate::Register for $name {
372 type Value = $val_type;
373 const OFFSET: usize = $offset;
374 fn from_raw(value: Self::Value) -> Self { $name(value) }
375 fn to_raw(&self) -> Self::Value { self.0 }
376 }
377 impl $crate::ReadableRegister 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> { $crate::RegisterProxy::new(mmio) }
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> { $crate::RegisterProxyMut::new(mmio) }
386 }
387 };
388
389 (
391 #[register(offset = $offset:expr, mode = WO)]
392 $(#[$attr:meta])*
393 pub struct $name:ident ($val_type:ty) { $($field_spec:tt)* }
394 ) => {
395 ::bitfield::bitfield! {
396 $(#[$attr])*
397 #[derive(Copy, Clone, PartialEq, Eq, Default)]
398 pub struct $name($val_type);
399 impl Debug;
400 $($field_spec)*
401 }
402
403 impl $crate::Register for $name {
404 type Value = $val_type;
405 const OFFSET: usize = $offset;
406 fn from_raw(value: Self::Value) -> Self { $name(value) }
407 fn to_raw(&self) -> Self::Value { self.0 }
408 }
409 impl $crate::WritableRegister for $name {}
410
411 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
412 type ReadProxy<'a> = $crate::RegisterProxy<'a, M, $name> where M: 'a;
413 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> { $crate::RegisterProxy::new(mmio) }
414 }
415 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
416 type WriteProxy<'a> = $crate::RegisterProxyMut<'a, M, $name> where M: 'a;
417 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> { $crate::RegisterProxyMut::new(mmio) }
418 }
419 };
420
421 (
423 #[register(offset = $offset:expr, mode = RW)]
424 $(#[$attr:meta])*
425 pub struct $name:ident ($val_type:ty) { $($field_spec:tt)* }
426 ) => {
427 ::bitfield::bitfield! {
428 $(#[$attr])*
429 #[derive(Copy, Clone, PartialEq, Eq, Default)]
430 pub struct $name($val_type);
431 impl Debug;
432 $($field_spec)*
433 }
434
435 impl $crate::Register for $name {
436 type Value = $val_type;
437 const OFFSET: usize = $offset;
438 fn from_raw(value: Self::Value) -> Self { $name(value) }
439 fn to_raw(&self) -> Self::Value { self.0 }
440 }
441 impl $crate::ReadableRegister for $name {}
442 impl $crate::WritableRegister for $name {}
443
444 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
445 type ReadProxy<'a> = $crate::RegisterProxy<'a, M, $name> where M: 'a;
446 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> { $crate::RegisterProxy::new(mmio) }
447 }
448 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
449 type WriteProxy<'a> = $crate::RegisterProxyMut<'a, M, $name> where M: 'a;
450 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> { $crate::RegisterProxyMut::new(mmio) }
451 }
452 };
453
454 (
456 #[register(offset = $offset:expr, mode = RO)]
457 $(#[$attr:meta])*
458 pub struct $name:ident ($val_type:ty) ;
459 ) => {
460 ::bitfield::bitfield! {
461 $(#[$attr])*
462 #[derive(Copy, Clone, PartialEq, Eq, Default)]
463 pub struct $name($val_type);
464 impl Debug;
465 }
466
467 impl $name {
468 pub fn value(&self) -> $val_type { self.0 }
469 }
470
471 impl $crate::Register for $name {
472 type Value = $val_type;
473 const OFFSET: usize = $offset;
474 fn from_raw(value: Self::Value) -> Self { $name(value) }
475 fn to_raw(&self) -> Self::Value { self.0 }
476 }
477 impl $crate::ReadableRegister for $name {}
478
479 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
480 type ReadProxy<'a> = $crate::RegisterProxy<'a, M, $name> where M: 'a;
481 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> { $crate::RegisterProxy::new(mmio) }
482 }
483 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
484 type WriteProxy<'a> = $crate::RegisterProxyMut<'a, M, $name> where M: 'a;
485 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> { $crate::RegisterProxyMut::new(mmio) }
486 }
487 };
488
489 (
491 #[register(offset = $offset:expr, mode = WO)]
492 $(#[$attr:meta])*
493 pub struct $name:ident ($val_type:ty) ;
494 ) => {
495 ::bitfield::bitfield! {
496 $(#[$attr])*
497 #[derive(Copy, Clone, PartialEq, Eq, Default)]
498 pub struct $name($val_type);
499 impl Debug;
500 }
501
502 impl $name {
503 pub fn set_value(&mut self, val: $val_type) { self.0 = val; }
504 }
505
506 impl $crate::Register for $name {
507 type Value = $val_type;
508 const OFFSET: usize = $offset;
509 fn from_raw(value: Self::Value) -> Self { $name(value) }
510 fn to_raw(&self) -> Self::Value { self.0 }
511 }
512 impl $crate::WritableRegister for $name {}
513
514 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
515 type ReadProxy<'a> = $crate::RegisterProxy<'a, M, $name> where M: 'a;
516 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> { $crate::RegisterProxy::new(mmio) }
517 }
518 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
519 type WriteProxy<'a> = $crate::RegisterProxyMut<'a, M, $name> where M: 'a;
520 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> { $crate::RegisterProxyMut::new(mmio) }
521 }
522 };
523
524 (
526 #[register(offset = $offset:expr, mode = RW)]
527 $(#[$attr:meta])*
528 pub struct $name:ident ($val_type:ty) ;
529 ) => {
530 ::bitfield::bitfield! {
531 $(#[$attr])*
532 #[derive(Copy, Clone, PartialEq, Eq, Default)]
533 pub struct $name($val_type);
534 impl Debug;
535 }
536
537 impl $name {
538 pub fn value(&self) -> $val_type { self.0 }
539 pub fn set_value(&mut self, val: $val_type) { self.0 = val; }
540 }
541
542 impl $crate::Register for $name {
543 type Value = $val_type;
544 const OFFSET: usize = $offset;
545 fn from_raw(value: Self::Value) -> Self { $name(value) }
546 fn to_raw(&self) -> Self::Value { self.0 }
547 }
548 impl $crate::ReadableRegister for $name {}
549 impl $crate::WritableRegister for $name {}
550
551 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
552 type ReadProxy<'a> = $crate::RegisterProxy<'a, M, $name> where M: 'a;
553 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> { $crate::RegisterProxy::new(mmio) }
554 }
555 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
556 type WriteProxy<'a> = $crate::RegisterProxyMut<'a, M, $name> where M: 'a;
557 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> { $crate::RegisterProxyMut::new(mmio) }
558 }
559 };
560
561 (
563 #[indexed_register(offset = $base_offset:expr, stride = $stride:expr, count = $count:expr, mode = RO)]
564 $(#[$attr:meta])*
565 pub struct $name:ident ($val_type:ty) { $($field_spec:tt)* }
566 ) => {
567 ::bitfield::bitfield! {
568 $(#[$attr])*
569 #[derive(Copy, Clone, PartialEq, Eq, Default)]
570 pub struct $name($val_type);
571 impl Debug;
572 $($field_spec)*
573 }
574
575 impl $crate::IndexedRegister for $name {
576 type Value = $val_type;
577 const BASE_OFFSET: usize = $base_offset;
578 const STRIDE: usize = $stride;
579 const COUNT: usize = $count;
580 fn from_raw(value: Self::Value) -> Self { $name(value) }
581 fn to_raw(&self) -> Self::Value { self.0 }
582 }
583 impl $crate::ReadableIndexedRegister for $name {}
584
585 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
586 type ReadProxy<'a> = $crate::IndexedRegisterProxy<'a, M, $name> where M: 'a;
587 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> { $crate::IndexedRegisterProxy::new(mmio) }
588 }
589 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
590 type WriteProxy<'a> = $crate::IndexedRegisterProxyMut<'a, M, $name> where M: 'a;
591 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> { $crate::IndexedRegisterProxyMut::new(mmio) }
592 }
593 };
594
595 (
597 #[indexed_register(offset = $base_offset:expr, stride = $stride:expr, count = $count:expr, mode = WO)]
598 $(#[$attr:meta])*
599 pub struct $name:ident ($val_type:ty) { $($field_spec:tt)* }
600 ) => {
601 ::bitfield::bitfield! {
602 $(#[$attr])*
603 #[derive(Copy, Clone, PartialEq, Eq, Default)]
604 pub struct $name($val_type);
605 impl Debug;
606 $($field_spec)*
607 }
608
609 impl $crate::IndexedRegister for $name {
610 type Value = $val_type;
611 const BASE_OFFSET: usize = $base_offset;
612 const STRIDE: usize = $stride;
613 const COUNT: usize = $count;
614 fn from_raw(value: Self::Value) -> Self { $name(value) }
615 fn to_raw(&self) -> Self::Value { self.0 }
616 }
617 impl $crate::WritableIndexedRegister for $name {}
618
619 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
620 type ReadProxy<'a> = $crate::IndexedRegisterProxy<'a, M, $name> where M: 'a;
621 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> { $crate::IndexedRegisterProxy::new(mmio) }
622 }
623 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
624 type WriteProxy<'a> = $crate::IndexedRegisterProxyMut<'a, M, $name> where M: 'a;
625 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> { $crate::IndexedRegisterProxyMut::new(mmio) }
626 }
627 };
628
629 (
631 #[indexed_register(offset = $base_offset:expr, stride = $stride:expr, count = $count:expr, mode = RW)]
632 $(#[$attr:meta])*
633 pub struct $name:ident ($val_type:ty) { $($field_spec:tt)* }
634 ) => {
635 ::bitfield::bitfield! {
636 $(#[$attr])*
637 #[derive(Copy, Clone, PartialEq, Eq, Default)]
638 pub struct $name($val_type);
639 impl Debug;
640 $($field_spec)*
641 }
642
643 impl $crate::IndexedRegister for $name {
644 type Value = $val_type;
645 const BASE_OFFSET: usize = $base_offset;
646 const STRIDE: usize = $stride;
647 const COUNT: usize = $count;
648 fn from_raw(value: Self::Value) -> Self { $name(value) }
649 fn to_raw(&self) -> Self::Value { self.0 }
650 }
651 impl $crate::ReadableIndexedRegister for $name {}
652 impl $crate::WritableIndexedRegister for $name {}
653
654 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
655 type ReadProxy<'a> = $crate::IndexedRegisterProxy<'a, M, $name> where M: 'a;
656 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> { $crate::IndexedRegisterProxy::new(mmio) }
657 }
658 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
659 type WriteProxy<'a> = $crate::IndexedRegisterProxyMut<'a, M, $name> where M: 'a;
660 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> { $crate::IndexedRegisterProxyMut::new(mmio) }
661 }
662 };
663
664 (
666 #[indexed_register(offset = $base_offset:expr, stride = $stride:expr, count = $count:expr, mode = RO)]
667 $(#[$attr:meta])*
668 pub struct $name:ident ($val_type:ty) ;
669 ) => {
670 ::bitfield::bitfield! {
671 $(#[$attr])*
672 #[derive(Copy, Clone, PartialEq, Eq, Default)]
673 pub struct $name($val_type);
674 impl Debug;
675 }
676
677 impl $name {
678 pub fn value(&self) -> $val_type { self.0 }
679 }
680
681 impl $crate::IndexedRegister for $name {
682 type Value = $val_type;
683 const BASE_OFFSET: usize = $base_offset;
684 const STRIDE: usize = $stride;
685 const COUNT: usize = $count;
686 fn from_raw(value: Self::Value) -> Self { $name(value) }
687 fn to_raw(&self) -> Self::Value { self.0 }
688 }
689 impl $crate::ReadableIndexedRegister for $name {}
690
691 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
692 type ReadProxy<'a> = $crate::IndexedRegisterProxy<'a, M, $name> where M: 'a;
693 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> { $crate::IndexedRegisterProxy::new(mmio) }
694 }
695 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
696 type WriteProxy<'a> = $crate::IndexedRegisterProxyMut<'a, M, $name> where M: 'a;
697 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> { $crate::IndexedRegisterProxyMut::new(mmio) }
698 }
699 };
700
701 (
703 #[indexed_register(offset = $base_offset:expr, stride = $stride:expr, count = $count:expr, mode = WO)]
704 $(#[$attr:meta])*
705 pub struct $name:ident ($val_type:ty) ;
706 ) => {
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 (
740 #[indexed_register(offset = $base_offset:expr, stride = $stride:expr, count = $count:expr, mode = RW)]
741 $(#[$attr:meta])*
742 pub struct $name:ident ($val_type:ty) ;
743 ) => {
744 ::bitfield::bitfield! {
745 $(#[$attr])*
746 #[derive(Copy, Clone, PartialEq, Eq, Default)]
747 pub struct $name($val_type);
748 impl Debug;
749 }
750
751 impl $name {
752 pub fn value(&self) -> $val_type { self.0 }
753 pub fn set_value(&mut self, val: $val_type) { self.0 = val; }
754 }
755
756 impl $crate::IndexedRegister for $name {
757 type Value = $val_type;
758 const BASE_OFFSET: usize = $base_offset;
759 const STRIDE: usize = $stride;
760 const COUNT: usize = $count;
761 fn from_raw(value: Self::Value) -> Self { $name(value) }
762 fn to_raw(&self) -> Self::Value { self.0 }
763 }
764 impl $crate::ReadableIndexedRegister for $name {}
765 impl $crate::WritableIndexedRegister for $name {}
766
767 impl<M: $crate::Mmio + ?Sized> $crate::RegisterReadAccess<M> for $name {
768 type ReadProxy<'a> = $crate::IndexedRegisterProxy<'a, M, $name> where M: 'a;
769 fn get_read_proxy<'a>(mmio: &'a M) -> Self::ReadProxy<'a> { $crate::IndexedRegisterProxy::new(mmio) }
770 }
771 impl<M: $crate::Mmio + ?Sized> $crate::RegisterWriteAccess<M> for $name {
772 type WriteProxy<'a> = $crate::IndexedRegisterProxyMut<'a, M, $name> where M: 'a;
773 fn get_write_proxy<'a>(mmio: &'a mut M) -> Self::WriteProxy<'a> { $crate::IndexedRegisterProxyMut::new(mmio) }
774 }
775 };
776}
777
778#[macro_export]
803macro_rules! register_block {
804 (
805 $(#[$attr:meta])*
806 $vis:vis struct $name:ident <$mmio:ident> {
807 $(
808 $(#[$field_attr:meta])*
809 $field_vis:vis $field:ident : $reg_type:ident
810 ),* $(,)?
811 }
812 ) => {
813 $(#[$attr])*
814 $vis struct $name<$mmio> {
815 pub mmio: $mmio,
816 }
817
818 impl<$mmio: $crate::Mmio> $name<$mmio> {
819 #[allow(dead_code)]
821 pub fn new(mmio: $mmio) -> Self {
822 Self { mmio }
823 }
824
825 $(
826 $crate::paste::paste! {
827 $(#[$field_attr])*
828 #[allow(dead_code)]
829 $field_vis fn $field(&self) -> <$reg_type as $crate::RegisterReadAccess<$mmio>>::ReadProxy<'_> {
830 <$reg_type as $crate::RegisterReadAccess<$mmio>>::get_read_proxy(&self.mmio)
831 }
832
833 $(#[$field_attr])*
834 #[allow(dead_code)]
835 $field_vis fn [<$field _mut>](&mut self) -> <$reg_type as $crate::RegisterWriteAccess<$mmio>>::WriteProxy<'_> {
836 <$reg_type as $crate::RegisterWriteAccess<$mmio>>::get_write_proxy(&mut self.mmio)
837 }
838 }
839 )*
840 }
841 };
842}
843
844#[cfg(test)]
845mod tests {
846 use super::*;
847 use crate::memory::Memory;
848 use core::mem::MaybeUninit;
849
850 register! {
851 #[register(offset = 4, mode = RW)]
852 pub struct TestReg(u32) {
853 pub field1, set_field1: 7, 0;
854 pub field2, set_field2: 15, 8;
855 }
856 }
857
858 register! {
859 #[register(offset = 8, mode = RO)]
860 pub struct ReadOnlyReg(u32) {
861 pub field1, _: 7, 0;
862 }
863 }
864
865 register! {
866 #[register(offset = 12, mode = WO)]
867 pub struct WriteOnlyReg(u32) {
868 _, set_field1: 7, 0;
869 }
870 }
871
872 register! {
873 #[indexed_register(offset = 16, stride = 4, count = 2, mode = RW)]
874 pub struct TestIndexedReg(u32) {
875 pub field1, set_field1: 7, 0;
876 }
877 }
878
879 register_block! {
880 pub struct TestBlock<M> {
881 pub test_reg: TestReg,
882 pub ro_reg: ReadOnlyReg,
883 pub wo_reg: WriteOnlyReg,
884 pub indexed: TestIndexedReg,
885 }
886 }
887
888 register_block! {
889 #[expect(dead_code)]
891 pub struct TestBlockWithAttributtes<M> {
892 pub test_reg: TestReg,
893
894 pub ro_reg: ReadOnlyReg,
896
897 pub wo_reg: WriteOnlyReg,
899 }
900 }
901
902 #[test]
903 fn test_register_read_write() {
904 let mut mem = MaybeUninit::<[u32; 8]>::zeroed();
905 let mut mmio = Memory::borrow_uninit(&mut mem);
906
907 let mut reg = TestReg::default();
908 reg.set_field1(0x12);
909 reg.set_field2(0x34);
910
911 reg.write(&mut mmio);
912
913 let reg2 = TestReg::read(&mmio);
914 assert_eq!(reg, reg2);
915 assert_eq!(reg2.field1(), 0x12);
916 assert_eq!(reg2.field2(), 0x34);
917 }
918
919 #[test]
920 fn test_update_reg() {
921 let mut mem = MaybeUninit::<[u32; 8]>::zeroed();
922 let mut mmio = Memory::borrow_uninit(&mut mem);
923
924 mmio.update_reg::<TestReg, _>(|reg| {
925 reg.set_field1(0xab);
926 });
927
928 let reg = mmio.read_reg::<TestReg>();
929 assert_eq!(reg.field1(), 0xab);
930 assert_eq!(reg.field2(), 0);
931 }
932
933 #[test]
934 fn test_register_proxy() {
935 let mut mem = MaybeUninit::<[u32; 8]>::zeroed();
936 let mut mmio = Memory::borrow_uninit(&mut mem);
937
938 mmio.store32(4, 0x1234);
940 let proxy = mmio.reg::<TestReg>();
941 assert_eq!(proxy.read().field1(), 0x34);
942
943 {
945 let mut proxy_mut = mmio.reg_mut::<TestReg>();
946 proxy_mut.update(|reg| {
947 reg.set_field1(0x56);
948 });
949 assert_eq!(proxy_mut.read().field1(), 0x56);
950
951 proxy_mut.write(TestReg(0x78));
952 }
953 assert_eq!(mmio.load32(4), 0x78);
954 }
955
956 #[test]
957 fn test_indexed_register() {
958 let mut mem = MaybeUninit::<[u32; 12]>::zeroed();
959 let mut mmio = Memory::borrow_uninit(&mut mem);
960
961 let mut reg = TestIndexedReg::default();
962 reg.set_field1(0x11);
963 reg.write_index(&mut mmio, 0);
964
965 reg.set_field1(0x22);
966 reg.write_index(&mut mmio, 1);
967
968 assert_eq!(mmio.load32(16), 0x11);
969 assert_eq!(mmio.load32(20), 0x22);
970
971 let reg0 = TestIndexedReg::read_index(&mmio, 0);
972 assert_eq!(reg0.field1(), 0x11);
973
974 let reg1 = TestIndexedReg::read_index(&mmio, 1);
975 assert_eq!(reg1.field1(), 0x22);
976 }
977
978 #[test]
979 fn test_indexed_register_proxy() {
980 let mut mem = MaybeUninit::<[u32; 12]>::zeroed();
981 let mut mmio = Memory::borrow_uninit(&mut mem);
982
983 {
984 let mut proxy = mmio.indexed_reg_mut::<TestIndexedReg>();
985 proxy.write(0, TestIndexedReg(0xaa));
986 proxy.update(1, |reg| reg.set_field1(0xbb));
987
988 assert_eq!(proxy.read(0).field1(), 0xaa);
989 assert_eq!(proxy.read(1).field1(), 0xbb);
990 }
991
992 assert_eq!(mmio.load32(16), 0xaa);
993 assert_eq!(mmio.load32(20), 0xbb);
994 }
995
996 #[test]
997 #[should_panic(expected = "Register index out of bounds")]
998 fn test_indexed_register_out_of_bounds_read() {
999 let mut mem = MaybeUninit::<[u32; 12]>::zeroed();
1000 let mmio = Memory::borrow_uninit(&mut mem);
1001 let _ = TestIndexedReg::read_index(&mmio, 2);
1002 }
1003
1004 #[test]
1005 #[should_panic(expected = "Register index out of bounds")]
1006 fn test_indexed_register_out_of_bounds_write() {
1007 let mut mem = MaybeUninit::<[u32; 12]>::zeroed();
1008 let mut mmio = Memory::borrow_uninit(&mut mem);
1009 let reg = TestIndexedReg::default();
1010 reg.write_index(&mut mmio, 2);
1011 }
1012
1013 #[test]
1014 fn test_register_block() {
1015 let mut mem = MaybeUninit::<[u32; 12]>::zeroed();
1016 let mmio = Memory::borrow_uninit(&mut mem);
1017 let mut block = TestBlock::new(mmio);
1018
1019 block.test_reg_mut().write(TestReg(0x1234));
1020 assert_eq!(block.mmio.load32(4), 0x1234);
1021
1022 block.mmio.store32(8, 0xabcd);
1023 assert_eq!(block.ro_reg().read().field1(), 0xcd);
1024
1025 block.wo_reg_mut().write(WriteOnlyReg(0x55));
1026 assert_eq!(block.mmio.load32(12), 0x55);
1027
1028 block.indexed_mut().write(0, TestIndexedReg(0x11));
1029 block.indexed_mut().write(1, TestIndexedReg(0x22));
1030 assert_eq!(block.mmio.load32(16), 0x11);
1031 assert_eq!(block.mmio.load32(20), 0x22);
1032
1033 let block = block;
1035 assert_eq!(block.test_reg().read().field1(), 0x34);
1036 assert_eq!(block.ro_reg().read().field1(), 0xcd);
1037 assert_eq!(block.indexed().read(0).field1(), 0x11);
1038 }
1039
1040 register! {
1041 #[register(offset = 4, mode = RW)]
1042 pub struct NewSyntaxReg(u32) {
1044 pub field1, set_field1: 7, 0;
1045 }
1046 }
1047
1048 register! {
1049 #[register(offset = 8, mode = RW)]
1050 pub struct FullWidthReg(u32);
1052 }
1053
1054 register! {
1055 #[indexed_register(offset = 12, stride = 4, count = 2, mode = RW)]
1056 pub struct NewSyntaxIndexedReg(u32) {
1058 pub field1, set_field1: 7, 0;
1059 }
1060 }
1061
1062 register! {
1063 #[register(offset = 0x20, mode = RW)]
1064 pub struct MultiReg1(u32);
1065 #[register(offset = 0x24, mode = RO)]
1066 pub struct MultiReg2(u32) {
1067 pub field1, _: 7, 0;
1068 }
1069 }
1070
1071 #[test]
1072 fn test_multi_register() {
1073 let mut mem = MaybeUninit::<[u32; 12]>::zeroed();
1074 let mut mmio = Memory::borrow_uninit(&mut mem);
1075
1076 let mut reg1 = MultiReg1::default();
1077 reg1.set_value(0x12345678);
1078 reg1.write(&mut mmio);
1079
1080 mmio.store32(0x24, 0xabcd);
1081
1082 let reg1_read = MultiReg1::read(&mmio);
1083 assert_eq!(reg1_read.value(), 0x12345678);
1084
1085 let reg2_read = MultiReg2::read(&mmio);
1086 assert_eq!(reg2_read.field1(), 0xcd);
1087 }
1088
1089 #[test]
1090 fn test_new_syntax() {
1091 let mut mem = MaybeUninit::<[u32; 8]>::zeroed();
1092 let mut mmio = Memory::borrow_uninit(&mut mem);
1093
1094 let mut reg = NewSyntaxReg::default();
1095 reg.set_field1(0x55);
1096 reg.write(&mut mmio);
1097
1098 let reg2 = NewSyntaxReg::read(&mmio);
1099 assert_eq!(reg2.field1(), 0x55);
1100 }
1101
1102 #[test]
1103 fn test_full_width() {
1104 let mut mem = MaybeUninit::<[u32; 8]>::zeroed();
1105 let mut mmio = Memory::borrow_uninit(&mut mem);
1106
1107 let mut reg = FullWidthReg::default();
1108 reg.set_value(0x12345678);
1109 reg.write(&mut mmio);
1110
1111 let reg2 = FullWidthReg::read(&mmio);
1112 assert_eq!(reg2.value(), 0x12345678);
1113 }
1114
1115 #[test]
1116 fn test_new_syntax_indexed() {
1117 let mut mem = MaybeUninit::<[u32; 8]>::zeroed();
1118 let mut mmio = Memory::borrow_uninit(&mut mem);
1119
1120 let mut reg = NewSyntaxIndexedReg::default();
1121 reg.set_field1(0xaa);
1122 reg.write_index(&mut mmio, 0);
1123
1124 reg.set_field1(0xbb);
1125 reg.write_index(&mut mmio, 1);
1126
1127 let reg0 = NewSyntaxIndexedReg::read_index(&mmio, 0);
1128 assert_eq!(reg0.field1(), 0xaa);
1129
1130 let reg1 = NewSyntaxIndexedReg::read_index(&mmio, 1);
1131 assert_eq!(reg1.field1(), 0xbb);
1132 }
1133}