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 /// pub struct ControlReg(u32) { 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 /// Note that the compiler will error out if the size of the setter's arg exceeds the 74 /// struct's storage size. 75 /// - Debug and Default implementations. 76 /// 77 /// Note: Field accessors and setters inherit the same visibility as the struct itself. 78 /// In the example above, both `mode()` and `set_mode()` methods will be `pub`. 79 /// 80 /// Fields are defined as follows: 81 /// 82 /// - `as <type>` simply returns the field value casted to <type>, typically `u32`, `u16`, `u8` or 83 /// `bool`. Note that `bool` fields must have a range of 1 bit. 84 /// - `as <type> => <into_type>` calls `<into_type>`'s `From::<<type>>` implementation and returns 85 /// the result. 86 /// - `as <type> ?=> <try_into_type>` calls `<try_into_type>`'s `TryFrom::<<type>>` implementation 87 /// and returns the result. This is useful with fields for which not all values are valid. 88 macro_rules! bitfield { 89 // Main entry point - defines the bitfield struct with fields 90 ($vis:vis struct $name:ident($storage:ty) $(, $comment:literal)? { $($fields:tt)* }) => { 91 bitfield!(@core $vis $name $storage $(, $comment)? { $($fields)* }); 92 }; 93 94 // All rules below are helpers. 95 96 // Defines the wrapper `$name` type, as well as its relevant implementations (`Debug`, 97 // `Default`, `BitOr`, and conversion to the value type) and field accessor methods. 98 (@core $vis:vis $name:ident $storage:ty $(, $comment:literal)? { $($fields:tt)* }) => { 99 $( 100 #[doc=$comment] 101 )? 102 #[repr(transparent)] 103 #[derive(Clone, Copy)] 104 $vis struct $name($storage); 105 106 impl ::core::ops::BitOr for $name { 107 type Output = Self; 108 109 fn bitor(self, rhs: Self) -> Self::Output { 110 Self(self.0 | rhs.0) 111 } 112 } 113 114 impl ::core::convert::From<$name> for $storage { 115 fn from(val: $name) -> $storage { 116 val.0 117 } 118 } 119 120 bitfield!(@fields_dispatcher $vis $name $storage { $($fields)* }); 121 }; 122 123 // Captures the fields and passes them to all the implementers that require field information. 124 // 125 // Used to simplify the matching rules for implementers, so they don't need to match the entire 126 // complex fields rule even though they only make use of part of it. 127 (@fields_dispatcher $vis:vis $name:ident $storage:ty { 128 $($hi:tt:$lo:tt $field:ident as $type:tt 129 $(?=> $try_into_type:ty)? 130 $(=> $into_type:ty)? 131 $(, $comment:literal)? 132 ; 133 )* 134 } 135 ) => { 136 bitfield!(@field_accessors $vis $name $storage { 137 $( 138 $hi:$lo $field as $type 139 $(?=> $try_into_type)? 140 $(=> $into_type)? 141 $(, $comment)? 142 ; 143 )* 144 }); 145 bitfield!(@debug $name { $($field;)* }); 146 bitfield!(@default $name { $($field;)* }); 147 }; 148 149 // Defines all the field getter/setter methods for `$name`. 150 ( 151 @field_accessors $vis:vis $name:ident $storage:ty { 152 $($hi:tt:$lo:tt $field:ident as $type:tt 153 $(?=> $try_into_type:ty)? 154 $(=> $into_type:ty)? 155 $(, $comment:literal)? 156 ; 157 )* 158 } 159 ) => { 160 $( 161 bitfield!(@check_field_bounds $hi:$lo $field as $type); 162 )* 163 164 #[allow(dead_code)] 165 impl $name { 166 $( 167 bitfield!(@field_accessor $vis $name $storage, $hi:$lo $field as $type 168 $(?=> $try_into_type)? 169 $(=> $into_type)? 170 $(, $comment)? 171 ; 172 ); 173 )* 174 } 175 }; 176 177 // Boolean fields must have `$hi == $lo`. 178 (@check_field_bounds $hi:tt:$lo:tt $field:ident as bool) => { 179 #[allow(clippy::eq_op)] 180 const _: () = { 181 ::kernel::build_assert!( 182 $hi == $lo, 183 concat!("boolean field `", stringify!($field), "` covers more than one bit") 184 ); 185 }; 186 }; 187 188 // Non-boolean fields must have `$hi >= $lo`. 189 (@check_field_bounds $hi:tt:$lo:tt $field:ident as $type:tt) => { 190 #[allow(clippy::eq_op)] 191 const _: () = { 192 ::kernel::build_assert!( 193 $hi >= $lo, 194 concat!("field `", stringify!($field), "`'s MSB is smaller than its LSB") 195 ); 196 }; 197 }; 198 199 // Catches fields defined as `bool` and convert them into a boolean value. 200 ( 201 @field_accessor $vis:vis $name:ident $storage:ty, $hi:tt:$lo:tt $field:ident as bool 202 => $into_type:ty $(, $comment:literal)?; 203 ) => { 204 bitfield!( 205 @leaf_accessor $vis $name $storage, $hi:$lo $field 206 { |f| <$into_type>::from(f != 0) } 207 bool $into_type => $into_type $(, $comment)?; 208 ); 209 }; 210 211 // Shortcut for fields defined as `bool` without the `=>` syntax. 212 ( 213 @field_accessor $vis:vis $name:ident $storage:ty, $hi:tt:$lo:tt $field:ident as bool 214 $(, $comment:literal)?; 215 ) => { 216 bitfield!( 217 @field_accessor $vis $name $storage, $hi:$lo $field as bool => bool $(, $comment)?; 218 ); 219 }; 220 221 // Catches the `?=>` syntax for non-boolean fields. 222 ( 223 @field_accessor $vis:vis $name:ident $storage:ty, $hi:tt:$lo:tt $field:ident as $type:tt 224 ?=> $try_into_type:ty $(, $comment:literal)?; 225 ) => { 226 bitfield!(@leaf_accessor $vis $name $storage, $hi:$lo $field 227 { |f| <$try_into_type>::try_from(f as $type) } $type $try_into_type => 228 ::core::result::Result< 229 $try_into_type, 230 <$try_into_type as ::core::convert::TryFrom<$type>>::Error 231 > 232 $(, $comment)?;); 233 }; 234 235 // Catches the `=>` syntax for non-boolean fields. 236 ( 237 @field_accessor $vis:vis $name:ident $storage:ty, $hi:tt:$lo:tt $field:ident as $type:tt 238 => $into_type:ty $(, $comment:literal)?; 239 ) => { 240 bitfield!(@leaf_accessor $vis $name $storage, $hi:$lo $field 241 { |f| <$into_type>::from(f as $type) } $type $into_type => $into_type $(, $comment)?;); 242 }; 243 244 // Shortcut for non-boolean fields defined without the `=>` or `?=>` syntax. 245 ( 246 @field_accessor $vis:vis $name:ident $storage:ty, $hi:tt:$lo:tt $field:ident as $type:tt 247 $(, $comment:literal)?; 248 ) => { 249 bitfield!( 250 @field_accessor $vis $name $storage, $hi:$lo $field as $type => $type $(, $comment)?; 251 ); 252 }; 253 254 // Generates the accessor methods for a single field. 255 ( 256 @leaf_accessor $vis:vis $name:ident $storage:ty, $hi:tt:$lo:tt $field:ident 257 { $process:expr } $prim_type:tt $to_type:ty => $res_type:ty $(, $comment:literal)?; 258 ) => { 259 ::kernel::macros::paste!( 260 const [<$field:upper _RANGE>]: ::core::ops::RangeInclusive<u8> = $lo..=$hi; 261 const [<$field:upper _MASK>]: $storage = { 262 // Generate mask for shifting 263 match ::core::mem::size_of::<$storage>() { 264 1 => ::kernel::bits::genmask_u8($lo..=$hi) as $storage, 265 2 => ::kernel::bits::genmask_u16($lo..=$hi) as $storage, 266 4 => ::kernel::bits::genmask_u32($lo..=$hi) as $storage, 267 8 => ::kernel::bits::genmask_u64($lo..=$hi) as $storage, 268 _ => ::kernel::build_error!("Unsupported storage type size") 269 } 270 }; 271 const [<$field:upper _SHIFT>]: u32 = $lo; 272 ); 273 274 $( 275 #[doc="Returns the value of this field:"] 276 #[doc=$comment] 277 )? 278 #[inline(always)] 279 $vis fn $field(self) -> $res_type { 280 ::kernel::macros::paste!( 281 const MASK: $storage = $name::[<$field:upper _MASK>]; 282 const SHIFT: u32 = $name::[<$field:upper _SHIFT>]; 283 ); 284 let field = ((self.0 & MASK) >> SHIFT); 285 286 $process(field) 287 } 288 289 ::kernel::macros::paste!( 290 $( 291 #[doc="Sets the value of this field:"] 292 #[doc=$comment] 293 )? 294 #[inline(always)] 295 $vis fn [<set_ $field>](mut self, value: $to_type) -> Self { 296 const MASK: $storage = $name::[<$field:upper _MASK>]; 297 const SHIFT: u32 = $name::[<$field:upper _SHIFT>]; 298 let value = ($storage::from($prim_type::from(value)) << SHIFT) & MASK; 299 self.0 = (self.0 & !MASK) | value; 300 301 self 302 } 303 ); 304 }; 305 306 // Generates the `Debug` implementation for `$name`. 307 (@debug $name:ident { $($field:ident;)* }) => { 308 impl ::kernel::fmt::Debug for $name { 309 fn fmt(&self, f: &mut ::kernel::fmt::Formatter<'_>) -> ::kernel::fmt::Result { 310 f.debug_struct(stringify!($name)) 311 .field("<raw>", &::kernel::prelude::fmt!("{:#x}", &self.0)) 312 $( 313 .field(stringify!($field), &self.$field()) 314 )* 315 .finish() 316 } 317 } 318 }; 319 320 // Generates the `Default` implementation for `$name`. 321 (@default $name:ident { $($field:ident;)* }) => { 322 /// Returns a value for the bitfield where all fields are set to their default value. 323 impl ::core::default::Default for $name { 324 fn default() -> Self { 325 #[allow(unused_mut)] 326 let mut value = Self(Default::default()); 327 328 ::kernel::macros::paste!( 329 $( 330 value.[<set_ $field>](Default::default()); 331 )* 332 ); 333 334 value 335 } 336 } 337 }; 338 } 339