1 // SPDX-License-Identifier: GPL-2.0 2 3 //! Bitfield library for Rust structures 4 //! 5 //! Support for defining bitfields in Rust structures. Also used by the [`register!`] macro. 6 7 /// Defines a struct with accessors to access bits within an inner unsigned integer. 8 /// 9 /// # Syntax 10 /// 11 /// ```rust 12 /// use nova_core::bitfield; 13 /// 14 /// #[derive(Debug, Clone, Copy, Default)] 15 /// enum Mode { 16 /// #[default] 17 /// Low = 0, 18 /// High = 1, 19 /// Auto = 2, 20 /// } 21 /// 22 /// impl TryFrom<u8> for Mode { 23 /// type Error = u8; 24 /// fn try_from(value: u8) -> Result<Self, Self::Error> { 25 /// match value { 26 /// 0 => Ok(Mode::Low), 27 /// 1 => Ok(Mode::High), 28 /// 2 => Ok(Mode::Auto), 29 /// _ => Err(value), 30 /// } 31 /// } 32 /// } 33 /// 34 /// impl From<Mode> for u8 { 35 /// fn from(mode: Mode) -> u8 { 36 /// mode as u8 37 /// } 38 /// } 39 /// 40 /// #[derive(Debug, Clone, Copy, Default)] 41 /// enum State { 42 /// #[default] 43 /// Inactive = 0, 44 /// Active = 1, 45 /// } 46 /// 47 /// impl From<bool> for State { 48 /// fn from(value: bool) -> Self { 49 /// if value { State::Active } else { State::Inactive } 50 /// } 51 /// } 52 /// 53 /// impl From<State> for bool { 54 /// fn from(state: State) -> bool { 55 /// match state { 56 /// State::Inactive => false, 57 /// State::Active => true, 58 /// } 59 /// } 60 /// } 61 /// 62 /// bitfield! { 63 /// struct ControlReg { 64 /// 7:7 state as bool => State; 65 /// 3:0 mode as u8 ?=> Mode; 66 /// } 67 /// } 68 /// ``` 69 /// 70 /// This generates a struct with: 71 /// - Field accessors: `mode()`, `state()`, etc. 72 /// - Field setters: `set_mode()`, `set_state()`, etc. (supports chaining with builder pattern). 73 /// - Debug and Default implementations. 74 /// 75 /// Fields are defined as follows: 76 /// 77 /// - `as <type>` simply returns the field value casted to <type>, typically `u32`, `u16`, `u8` or 78 /// `bool`. Note that `bool` fields must have a range of 1 bit. 79 /// - `as <type> => <into_type>` calls `<into_type>`'s `From::<<type>>` implementation and returns 80 /// the result. 81 /// - `as <type> ?=> <try_into_type>` calls `<try_into_type>`'s `TryFrom::<<type>>` implementation 82 /// and returns the result. This is useful with fields for which not all values are valid. 83 macro_rules! bitfield { 84 // Main entry point - defines the bitfield struct with fields 85 (struct $name:ident $(, $comment:literal)? { $($fields:tt)* }) => { 86 bitfield!(@core $name $(, $comment)? { $($fields)* }); 87 }; 88 89 // All rules below are helpers. 90 91 // Defines the wrapper `$name` type, as well as its relevant implementations (`Debug`, 92 // `Default`, `BitOr`, and conversion to the value type) and field accessor methods. 93 (@core $name:ident $(, $comment:literal)? { $($fields:tt)* }) => { 94 $( 95 #[doc=$comment] 96 )? 97 #[repr(transparent)] 98 #[derive(Clone, Copy)] 99 pub(crate) struct $name(u32); 100 101 impl ::core::ops::BitOr for $name { 102 type Output = Self; 103 104 fn bitor(self, rhs: Self) -> Self::Output { 105 Self(self.0 | rhs.0) 106 } 107 } 108 109 impl ::core::convert::From<$name> for u32 { 110 fn from(val: $name) -> u32 { 111 val.0 112 } 113 } 114 115 bitfield!(@fields_dispatcher $name { $($fields)* }); 116 }; 117 118 // Captures the fields and passes them to all the implementers that require field information. 119 // 120 // Used to simplify the matching rules for implementers, so they don't need to match the entire 121 // complex fields rule even though they only make use of part of it. 122 (@fields_dispatcher $name:ident { 123 $($hi:tt:$lo:tt $field:ident as $type:tt 124 $(?=> $try_into_type:ty)? 125 $(=> $into_type:ty)? 126 $(, $comment:literal)? 127 ; 128 )* 129 } 130 ) => { 131 bitfield!(@field_accessors $name { 132 $( 133 $hi:$lo $field as $type 134 $(?=> $try_into_type)? 135 $(=> $into_type)? 136 $(, $comment)? 137 ; 138 )* 139 }); 140 bitfield!(@debug $name { $($field;)* }); 141 bitfield!(@default $name { $($field;)* }); 142 }; 143 144 // Defines all the field getter/setter methods for `$name`. 145 ( 146 @field_accessors $name:ident { 147 $($hi:tt:$lo:tt $field:ident as $type:tt 148 $(?=> $try_into_type:ty)? 149 $(=> $into_type:ty)? 150 $(, $comment:literal)? 151 ; 152 )* 153 } 154 ) => { 155 $( 156 bitfield!(@check_field_bounds $hi:$lo $field as $type); 157 )* 158 159 #[allow(dead_code)] 160 impl $name { 161 $( 162 bitfield!(@field_accessor $name $hi:$lo $field as $type 163 $(?=> $try_into_type)? 164 $(=> $into_type)? 165 $(, $comment)? 166 ; 167 ); 168 )* 169 } 170 }; 171 172 // Boolean fields must have `$hi == $lo`. 173 (@check_field_bounds $hi:tt:$lo:tt $field:ident as bool) => { 174 #[allow(clippy::eq_op)] 175 const _: () = { 176 ::kernel::build_assert!( 177 $hi == $lo, 178 concat!("boolean field `", stringify!($field), "` covers more than one bit") 179 ); 180 }; 181 }; 182 183 // Non-boolean fields must have `$hi >= $lo`. 184 (@check_field_bounds $hi:tt:$lo:tt $field:ident as $type:tt) => { 185 #[allow(clippy::eq_op)] 186 const _: () = { 187 ::kernel::build_assert!( 188 $hi >= $lo, 189 concat!("field `", stringify!($field), "`'s MSB is smaller than its LSB") 190 ); 191 }; 192 }; 193 194 // Catches fields defined as `bool` and convert them into a boolean value. 195 ( 196 @field_accessor $name:ident $hi:tt:$lo:tt $field:ident as bool => $into_type:ty 197 $(, $comment:literal)?; 198 ) => { 199 bitfield!( 200 @leaf_accessor $name $hi:$lo $field 201 { |f| <$into_type>::from(if f != 0 { true } else { false }) } 202 bool $into_type => $into_type $(, $comment)?; 203 ); 204 }; 205 206 // Shortcut for fields defined as `bool` without the `=>` syntax. 207 ( 208 @field_accessor $name:ident $hi:tt:$lo:tt $field:ident as bool $(, $comment:literal)?; 209 ) => { 210 bitfield!(@field_accessor $name $hi:$lo $field as bool => bool $(, $comment)?;); 211 }; 212 213 // Catches the `?=>` syntax for non-boolean fields. 214 ( 215 @field_accessor $name:ident $hi:tt:$lo:tt $field:ident as $type:tt ?=> $try_into_type:ty 216 $(, $comment:literal)?; 217 ) => { 218 bitfield!(@leaf_accessor $name $hi:$lo $field 219 { |f| <$try_into_type>::try_from(f as $type) } $type $try_into_type => 220 ::core::result::Result< 221 $try_into_type, 222 <$try_into_type as ::core::convert::TryFrom<$type>>::Error 223 > 224 $(, $comment)?;); 225 }; 226 227 // Catches the `=>` syntax for non-boolean fields. 228 ( 229 @field_accessor $name:ident $hi:tt:$lo:tt $field:ident as $type:tt => $into_type:ty 230 $(, $comment:literal)?; 231 ) => { 232 bitfield!(@leaf_accessor $name $hi:$lo $field 233 { |f| <$into_type>::from(f as $type) } $type $into_type => $into_type $(, $comment)?;); 234 }; 235 236 // Shortcut for non-boolean fields defined without the `=>` or `?=>` syntax. 237 ( 238 @field_accessor $name:ident $hi:tt:$lo:tt $field:ident as $type:tt 239 $(, $comment:literal)?; 240 ) => { 241 bitfield!(@field_accessor $name $hi:$lo $field as $type => $type $(, $comment)?;); 242 }; 243 244 // Generates the accessor methods for a single field. 245 ( 246 @leaf_accessor $name:ident $hi:tt:$lo:tt $field:ident 247 { $process:expr } $prim_type:tt $to_type:ty => $res_type:ty $(, $comment:literal)?; 248 ) => { 249 ::kernel::macros::paste!( 250 const [<$field:upper _RANGE>]: ::core::ops::RangeInclusive<u8> = $lo..=$hi; 251 const [<$field:upper _MASK>]: u32 = ((((1 << $hi) - 1) << 1) + 1) - ((1 << $lo) - 1); 252 const [<$field:upper _SHIFT>]: u32 = Self::[<$field:upper _MASK>].trailing_zeros(); 253 ); 254 255 $( 256 #[doc="Returns the value of this field:"] 257 #[doc=$comment] 258 )? 259 #[inline(always)] 260 pub(crate) fn $field(self) -> $res_type { 261 ::kernel::macros::paste!( 262 const MASK: u32 = $name::[<$field:upper _MASK>]; 263 const SHIFT: u32 = $name::[<$field:upper _SHIFT>]; 264 ); 265 let field = ((self.0 & MASK) >> SHIFT); 266 267 $process(field) 268 } 269 270 ::kernel::macros::paste!( 271 $( 272 #[doc="Sets the value of this field:"] 273 #[doc=$comment] 274 )? 275 #[inline(always)] 276 pub(crate) fn [<set_ $field>](mut self, value: $to_type) -> Self { 277 const MASK: u32 = $name::[<$field:upper _MASK>]; 278 const SHIFT: u32 = $name::[<$field:upper _SHIFT>]; 279 let value = (u32::from($prim_type::from(value)) << SHIFT) & MASK; 280 self.0 = (self.0 & !MASK) | value; 281 282 self 283 } 284 ); 285 }; 286 287 // Generates the `Debug` implementation for `$name`. 288 (@debug $name:ident { $($field:ident;)* }) => { 289 impl ::kernel::fmt::Debug for $name { 290 fn fmt(&self, f: &mut ::kernel::fmt::Formatter<'_>) -> ::kernel::fmt::Result { 291 f.debug_struct(stringify!($name)) 292 .field("<raw>", &::kernel::prelude::fmt!("{:#x}", &self.0)) 293 $( 294 .field(stringify!($field), &self.$field()) 295 )* 296 .finish() 297 } 298 } 299 }; 300 301 // Generates the `Default` implementation for `$name`. 302 (@default $name:ident { $($field:ident;)* }) => { 303 /// Returns a value for the bitfield where all fields are set to their default value. 304 impl ::core::default::Default for $name { 305 fn default() -> Self { 306 #[allow(unused_mut)] 307 let mut value = Self(Default::default()); 308 309 ::kernel::macros::paste!( 310 $( 311 value.[<set_ $field>](Default::default()); 312 )* 313 ); 314 315 value 316 } 317 } 318 }; 319 } 320