#[macro_export]
macro_rules! define_mmio_register {
($(#[$reg_attr:meta])*
$reg_name:ident: $num_ty:ty { $(
$(#[$field_attr:meta])*
$perm:ident $name:ident: $from:literal $( .. $to:literal =
$(#[$kind_attr:meta])*
$kind_type:ident $kind_name:ident [
$(
$(#[$kind_variant_attr:meta])*
$kind_variant:ident = $kind_variant_val:expr
),*$(,)?
]
)?
),*$(,)?
}) => {
const _: fn() = || {
fn assert_impl<T: $crate::Int>() {}
assert_impl::<$num_ty>();
};
$($(
$crate::__generate_field_kinds__!($num_ty, $perm, $from .. $to,
$(#[$kind_attr])*
$kind_type $kind_name [
$(
$(#[$kind_variant_attr])*
$kind_variant = $kind_variant_val
),*
]
);
)*)?
$(
$(#[$field_attr])*
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[allow(non_camel_case_types)]
pub struct $name($crate::mmio::VolAddr<$num_ty>);
)*
$(#[$reg_attr])*
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct $reg_name($crate::mmio::VolAddr<$num_ty>);
#[allow(dead_code)]
impl $reg_name {
#[inline]
pub const fn new(addr: $crate::mmio::VolAddr<$num_ty>) -> Self {
Self(addr)
}
$crate::__generate_if_perm__! { @read
pub fn get(self) -> $num_ty {
$crate::mmio::VolAddr::<$num_ty>::read(self.0)
}
=> $($perm) *
}
$crate::__generate_if_perm__! { @write
pub fn set(self, val: $num_ty) {
$crate::mmio::VolAddr::<$num_ty>::write(self.0, val);
}
=> $($perm) *
}
$crate::__generate_if_perm__! { @read
pub fn is_set<P: $crate::perm::Permission>(self, field: $crate::Field<$num_ty, P>) -> ::core::primitive::bool {
let val = $crate::mmio::VolAddr::<$num_ty>::read(self.0);
$crate::Field::<$num_ty, P>::read(field, val) != 0
}
=> $($perm) *
}
$crate::__generate_if_perm__! { @read
pub fn read<P: $crate::perm::Permission>(self, field: $crate::Field<$num_ty, P>) -> $num_ty {
let val = $crate::mmio::VolAddr::<$num_ty>::read(self.0);
$crate::Field::<$num_ty, P>::read(field, val)
}
=> $($perm) *
}
$crate::__generate_if_perm__! { @write
pub fn write(self, val: $crate::Value<$num_ty>) {
let val = $crate::Value::<$num_ty>::modify(val, 0);
$crate::mmio::VolAddr::<$num_ty>::write(self.0, val);
}
=> $($perm) *
}
$crate::__generate_if_perm__! { @read_write
pub fn modify(self, val: $crate::Value<$num_ty>) {
let reg = $crate::mmio::VolAddr::<$num_ty>::read(self.0);
let reg = $crate::Value::<$num_ty>::modify(val, reg);
$crate::mmio::VolAddr::<$num_ty>::write(self.0, reg);
}
=> $($perm) *
}
$(#[allow(non_snake_case)]
$(#[$field_attr])*
pub fn $name(&self) -> $name {
$name(self.0)
})*
}
$(
$crate::define_mmio_register!(@internal, $num_ty, $perm $name: $from $(.. $to =
$kind_type $kind_name [
$($kind_variant = $kind_variant_val),*
]
)?);
)*
};
(@internal, $num_ty:ty, rw $name:ident: $from:literal .. $to:literal = flags $kind_name:ident [
$($kind_variant:ident = $kind_variant_val:expr),*
]) => {
$crate::define_mmio_register!(@internal, $num_ty, r $name: $from .. $to = flags $kind_name [
$($kind_variant = $kind_variant_val),*
]);
$crate::define_mmio_register!(@internal, $num_ty, w $name: $from .. $to = flags $kind_name [
$($kind_variant = $kind_variant_val),*
]);
};
(@internal, $num_ty:ty, r $name:ident: $from:literal .. $to:literal = flags $kind_name:ident [
$($kind_variant:ident = $kind_variant_val:expr),*
]) => {
impl $name {
#[allow(unused)]
pub fn get(&self) -> $kind_name {
let val = $crate::mmio::VolAddr::<$num_ty>::read(self.0);
$kind_name::from_bits_truncate($crate::get_bits(val, ($from, $to)))
}
}
};
(@internal, $num_ty:ty, w $name:ident: $from:literal .. $to:literal = flags $kind_name:ident [
$($kind_variant:ident = $kind_variant_val:expr),*
]) => {
impl $name {
#[allow(unused)]
pub fn set(&self, flags: $kind_name) {
let bits = $kind_name::bits(&flags);
let val = $crate::mmio::VolAddr::<$num_ty>::read(self.0);
$crate::mmio::VolAddr::<$num_ty>::write(self.0, $crate::set_bits(val, ($from, $to), bits));
}
}
};
(@internal, $num_ty:ty, rw $name:ident: $from:literal .. $to:literal = enum $kind_name:ident [
$($kind_variant:ident = $kind_variant_val:expr),*
]) => {
$crate::define_mmio_register!(@internal, $num_ty, r $name: $from .. $to = enum $kind_name [
$($kind_variant = $kind_variant_val),*
]);
$crate::define_mmio_register!(@internal, $num_ty, w $name: $from .. $to = enum $kind_name [
$($kind_variant = $kind_variant_val),*
]);
};
(@internal, $num_ty:ty, r $name:ident: $from:literal .. $to:literal = enum $kind_name:ident [
$($kind_variant:ident = $kind_variant_val:expr),*
]) => {
impl $name {
#[allow(unused)]
pub fn get(&self) -> ::core::option::Option<$kind_name> {
let val = $crate::mmio::VolAddr::<$num_ty>::read(self.0);
match $crate::get_bits(val, ($from, $to)) {
$($kind_variant_val => ::core::option::Option::Some($kind_name::$kind_variant),)*
_ => ::core::option::Option::None,
}
}
}
};
(@internal, $num_ty:ty, w $name:ident: $from:literal .. $to:literal = enum $kind_name:ident [
$($kind_variant:ident = $kind_variant_val:expr),*
]) => {
impl $name {
#[allow(unused)]
pub fn set(&self, val: $kind_name) {
let bits = match val {
$($kind_name::$kind_variant => $kind_variant_val,)*
};
let val = $crate::mmio::VolAddr::<$num_ty>::read(self.0);
let val = $crate::set_bits(val, ($from, $to), bits);
$crate::mmio::VolAddr::<$num_ty>::write(self.0, val);
}
}
};
(@internal, $num_ty:ty, $perm:ident $name:ident: $bit:literal) => {
impl $name {
#[allow(unused)]
pub const FIELD: $crate::Field<$num_ty, $crate::__perm_for_name__!($perm)> = $crate::Field::<$num_ty, _>::new(1 << $bit);
}
$crate::define_mmio_register!(@internal_bit, $num_ty, $perm $name: $bit);
};
(@internal_bit, $num_ty:ty, rw $name:ident: $bit:literal) => {
$crate::define_mmio_register!(@internal_bit, $num_ty, r $name: $bit);
$crate::define_mmio_register!(@internal_bit, $num_ty, w $name: $bit);
};
(@internal_bit, $num_ty:ty, r $name:ident: $bit:literal) => {
impl $name {
#[allow(unused)]
pub fn get(&self) -> ::core::primitive::bool {
let val = $crate::mmio::VolAddr::<$num_ty>::read(self.0);
val & (1 << $bit) != 0
}
}
};
(@internal_bit, $num_ty:ty, w $name:ident: $bit:literal) => {
impl $name {
#[allow(unused)]
pub const SET: $crate::Value<$num_ty> = $crate::Value::<$num_ty>::new(1 << $bit, 1 << $bit);
#[allow(unused)]
pub const CLEAR: $crate::Value<$num_ty> = $crate::Value::<$num_ty>::new(1 << $bit, 0);
#[allow(unused)]
pub fn set(&self, x: ::core::primitive::bool) {
const MASK: $num_ty = 1 << $bit;
let val = $crate::mmio::VolAddr::<$num_ty>::read(self.0);
let val = match x {
true => val | MASK,
false => val & !MASK,
};
$crate::mmio::VolAddr::<$num_ty>::write(self.0, val);
}
}
};
}
#[macro_export]
macro_rules! define_mmio_struct {
($(#[$attr:meta])*
$pub:vis struct $name:ident {$(
$(#[$field_attr:meta])*
($field_offset:expr => $field_name:ident: $field_ty:ty)
),*$(,)?}) => { $crate::defile::item! {
$(#[$attr])*
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
$pub struct $name($crate::mmio::VolAddr<u8>);
impl $name {
#[allow(unused)]
pub const unsafe fn new(addr: ::core::primitive::usize) -> Self {
Self($crate::mmio::VolAddr::<u8>::new(addr))
}
$( $crate::define_mmio_struct!(@@create_field, $(#[$field_attr])*, $field_name, @$field_ty, $field_offset); )*
}
}};
(@create_field, $(#[$attr:meta])*, $name:ident, [$T:ty; $N:expr], $off:expr) => {
$(#[$attr])*
#[allow(unused)]
pub fn $name(&self, idx: usize) -> $T {
<$T>::new(unsafe {
$crate::mmio::VolAddr::cast(
$crate::mmio::VolAddr::offset(self.0, ($off + <$T>::size() * idx) as isize)
)
})
}
};
(@create_field, $(#[$attr:meta])*, $name:ident, $T:ty, $off:expr) => {
$(#[$attr])*
#[allow(unused, non_snake_case)]
pub fn $name(&self) -> $T {
<$T>::new(unsafe {
$crate::mmio::VolAddr::cast(
$crate::mmio::VolAddr::offset(self.0, $off)
)
})
}
};
}