tock_registers/
fields.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Register bitfield types and macros
6//!
7//! To conveniently access and manipulate fields of a register, this library
8//! provides types and macros to describe and access bitfields of a
9//! register. This can be especially useful in conjunction with the APIs defined
10//! in [`interfaces`](crate::interfaces), which make use of these types and
11//! hence allow to access and manipulate bitfields of proper registers directly.
12//!
13//! A specific section (bitfield) in a register is described by the [`Field`]
14//! type, consisting of an unshifted bitmask over the base register [`UIntLike`]
15//! type, and a shift parameter. It is further associated with a specific
16//! [`RegisterLongName`], which can prevent its use with incompatible registers.
17//!
18//! A value of a section of a register is described by the [`FieldValue`]
19//! type. It stores the information of the respective section in the register,
20//! as well as the associated value. A [`FieldValue`] can be created from a
21//! [`Field`] through the [`val`](Field::val) method.
22//!
23//! ## `register_bitfields` macro
24//!
25//! For defining register layouts with an associated [`RegisterLongName`], along
26//! with [`Field`]s and matching [`FieldValue`]s, a convenient macro-based
27//! interface can be used.
28//!
29//! The following example demonstrates how two registers can be defined, over a
30//! `u32` base type:
31//!
32//! ```rust
33//! # use tock_registers::register_bitfields;
34//! # use tock_registers::registers::InMemoryRegister;
35//! # use tock_registers::interfaces::{Readable, ReadWriteable};
36//! register_bitfields![u32,
37//!     Uart [
38//!         ENABLE OFFSET(0) NUMBITS(4) [
39//!             ON = 8,
40//!             OFF = 0
41//!         ]
42//!     ],
43//!     Psel [
44//!         PIN OFFSET(0) NUMBITS(6),
45//!         CONNECT OFFSET(31) NUMBITS(1)
46//!     ],
47//! ];
48//!
49//! // In this scope, `Uart` is a module, representing the register and its
50//! // fields. `Uart::Register` is a `RegisterLongName` type identifying this
51//! // register. `Uart::ENABLE` is a field covering the first 4 bits of this
52//! // register. `Uart::ENABLE::ON` is a `FieldValue` over that field, with the
53//! // associated value 8. We can now use the types like so:
54//! let reg: InMemoryRegister<u32, Uart::Register> = InMemoryRegister::new(0);
55//! assert!(reg.read(Uart::ENABLE) == 0x00000000);
56//! reg.modify(Uart::ENABLE::ON);
57//! assert!(reg.get() == 0x00000008);
58//!
59//! use tock_registers::interfaces::Debuggable;
60//! assert!(
61//!     &format!("{:?}", reg.debug())
62//!     == "Uart { ENABLE: ON }"
63//! );
64//! ```
65
66// The register interface uses `+` in a way that is fine for bitfields, but
67// looks unusual (and perhaps problematic) to a linter. We just ignore those
68// lints for this file.
69#![allow(clippy::suspicious_op_assign_impl)]
70#![allow(clippy::suspicious_arithmetic_impl)]
71
72use core::marker::PhantomData;
73use core::ops::{Add, AddAssign};
74
75use crate::{RegisterLongName, UIntLike};
76
77/// Specific section of a register.
78///
79/// For the Field, the mask is unshifted, ie. the LSB should always be set.
80pub struct Field<T: UIntLike, R: RegisterLongName> {
81    pub mask: T,
82    pub shift: usize,
83    associated_register: PhantomData<R>,
84}
85
86impl<T: UIntLike, R: RegisterLongName> Field<T, R> {
87    pub const fn new(mask: T, shift: usize) -> Field<T, R> {
88        Field {
89            mask,
90            shift,
91            associated_register: PhantomData,
92        }
93    }
94
95    #[inline]
96    pub fn read(self, val: T) -> T {
97        (val & (self.mask << self.shift)) >> self.shift
98    }
99
100    #[inline]
101    /// Check if one or more bits in a field are set
102    pub fn is_set(self, val: T) -> bool {
103        val & (self.mask << self.shift) != T::zero()
104    }
105
106    #[inline]
107    /// Read value of the field as an enum member
108    ///
109    /// This method expects to be passed the unasked and unshifted register
110    /// value, extracts the field value by calling [`Field::read`] and
111    /// subsequently passes that value to the [`TryFromValue`] implementation on
112    /// the passed enum type.
113    ///
114    /// The [`register_bitfields!`](crate::register_bitfields) macro will
115    /// generate an enum containing the various named field variants and
116    /// implementing the required [`TryFromValue`] trait. It is accessible as
117    /// `$REGISTER_NAME::$FIELD_NAME::Value`.
118    ///
119    /// This method can be useful to symbolically represent read register field
120    /// states throughout the codebase and to enforce exhaustive matches over
121    /// all defined valid register field values.
122    ///
123    /// ## Usage Example
124    ///
125    /// ```rust
126    /// # use tock_registers::interfaces::Readable;
127    /// # use tock_registers::registers::InMemoryRegister;
128    /// # use tock_registers::register_bitfields;
129    /// register_bitfields![u8,
130    ///     EXAMPLEREG [
131    ///         TESTFIELD OFFSET(3) NUMBITS(3) [
132    ///             Foo = 2,
133    ///             Bar = 3,
134    ///             Baz = 6,
135    ///         ],
136    ///     ],
137    /// ];
138    ///
139    /// assert_eq!(
140    ///     EXAMPLEREG::TESTFIELD.read_as_enum::<EXAMPLEREG::TESTFIELD::Value>(0x9C).unwrap(),
141    ///     EXAMPLEREG::TESTFIELD::Value::Bar
142    /// );
143    /// ```
144    pub fn read_as_enum<E: TryFromValue<T, EnumType = E>>(self, val: T) -> Option<E> {
145        E::try_from_value(self.read(val))
146    }
147}
148
149// #[derive(Copy, Clone)] won't work here because it will use incorrect bounds,
150// as a result of using a PhantomData over the generic R. The PhantomData<R>
151// implements Copy regardless of whether R does, but the #[derive(Copy, Clone)]
152// generates
153//
154//    #[automatically_derived]
155//    #[allow(unused_qualifications)]
156//    impl<T: ::core::marker::Copy + UIntLike,
157//         R: ::core::marker::Copy + RegisterLongName>
158//            ::core::marker::Copy for Field<T, R> {}
159//
160// , so Field will only implement Copy if R: Copy.
161//
162// Manually implementing Clone and Copy works around this issue.
163//
164// Relevant Rust issue: https://github.com/rust-lang/rust/issues/26925
165impl<T: UIntLike, R: RegisterLongName> Clone for Field<T, R> {
166    fn clone(&self) -> Self {
167        *self
168    }
169}
170impl<T: UIntLike, R: RegisterLongName> Copy for Field<T, R> {}
171
172macro_rules! Field_impl_for {
173    ($type:ty) => {
174        impl<R: RegisterLongName> Field<$type, R> {
175            pub const fn val(&self, value: $type) -> FieldValue<$type, R> {
176                FieldValue::<$type, R>::new(self.mask, self.shift, value)
177            }
178        }
179    };
180}
181
182Field_impl_for!(u8);
183Field_impl_for!(u16);
184Field_impl_for!(u32);
185Field_impl_for!(u64);
186Field_impl_for!(u128);
187Field_impl_for!(usize);
188
189/// Values for the specific register fields.
190///
191/// For the FieldValue, the masks and values are shifted into their actual
192/// location in the register.
193#[derive(Copy, Clone)]
194pub struct FieldValue<T: UIntLike, R: RegisterLongName> {
195    mask: T,
196    pub value: T,
197    associated_register: PhantomData<R>,
198}
199
200macro_rules! FieldValue_impl_for {
201    ($type:ty) => {
202        // Necessary to split the implementation of new() out because the
203        // bitwise math isn't treated as const when the type is generic.
204        // Tracking issue: https://github.com/rust-lang/rfcs/pull/2632
205        impl<R: RegisterLongName> FieldValue<$type, R> {
206            pub const fn new(mask: $type, shift: usize, value: $type) -> Self {
207                FieldValue {
208                    mask: mask << shift,
209                    value: (value & mask) << shift,
210                    associated_register: PhantomData,
211                }
212            }
213        }
214
215        // Necessary to split the implementation of From<> out because of the
216        // orphan rule for foreign trait implementation (see
217        // [E0210](https://doc.rust-lang.org/error-index.html#E0210)).
218        impl<R: RegisterLongName> From<FieldValue<$type, R>> for $type {
219            fn from(val: FieldValue<$type, R>) -> $type {
220                val.value
221            }
222        }
223    };
224}
225
226FieldValue_impl_for!(u8);
227FieldValue_impl_for!(u16);
228FieldValue_impl_for!(u32);
229FieldValue_impl_for!(u64);
230FieldValue_impl_for!(u128);
231FieldValue_impl_for!(usize);
232
233impl<T: UIntLike, R: RegisterLongName> FieldValue<T, R> {
234    #[inline]
235    pub fn none() -> Self {
236        Self {
237            mask: T::zero(),
238            value: T::zero(),
239            associated_register: PhantomData,
240        }
241    }
242
243    /// Get the raw bitmask represented by this FieldValue.
244    #[inline]
245    pub const fn mask(&self) -> T {
246        self.mask as T
247    }
248
249    #[inline]
250    pub fn read(&self, field: Field<T, R>) -> T {
251        field.read(self.value)
252    }
253
254    /// Modify fields in a register value
255    #[inline]
256    pub fn modify(self, val: T) -> T {
257        (val & !self.mask) | self.value
258    }
259
260    /// Check if any of the bits covered by the mask for this `FieldValue` and
261    /// set in the `FieldValue` are also set in the passed value
262    #[inline]
263    pub fn any_matching_bits_set(&self, val: T) -> bool {
264        val & self.mask & self.value != T::zero()
265    }
266
267    /// Check if all specified parts of a field match
268    #[inline]
269    pub fn matches_all(&self, val: T) -> bool {
270        val & self.mask == self.value
271    }
272}
273
274// Combine two fields with the addition operator
275impl<T: UIntLike, R: RegisterLongName> Add for FieldValue<T, R> {
276    type Output = Self;
277
278    #[inline]
279    fn add(self, rhs: Self) -> Self {
280        FieldValue {
281            mask: self.mask | rhs.mask,
282            value: self.value | rhs.value,
283            associated_register: PhantomData,
284        }
285    }
286}
287
288// Combine two fields with the += operator
289impl<T: UIntLike, R: RegisterLongName> AddAssign for FieldValue<T, R> {
290    #[inline]
291    fn add_assign(&mut self, rhs: FieldValue<T, R>) {
292        self.mask |= rhs.mask;
293        self.value |= rhs.value;
294    }
295}
296
297/// Conversion of raw register value into enumerated values member. Implemented
298/// inside register_bitfields! macro for each bit field.
299pub trait TryFromValue<V> {
300    type EnumType;
301
302    fn try_from_value(v: V) -> Option<Self::EnumType>;
303}
304
305/// Helper macro for computing bitmask of variable number of bits
306#[macro_export]
307macro_rules! bitmask {
308    ($numbits:expr) => {
309        (1 << ($numbits - 1)) + ((1 << ($numbits - 1)) - 1)
310    };
311}
312
313/// Helper macro for defining register fields.
314#[macro_export]
315macro_rules! register_bitmasks {
316    {
317        // BITFIELD_NAME OFFSET(x)
318        $(#[$outer:meta])*
319        $valtype:ident, $reg_mod:ident, $reg_desc:ident, [
320            $( $(#[$inner:meta])* $field:ident OFFSET($offset:expr)),+ $(,)?
321        ]
322    } => {
323        $(#[$outer])*
324        $( $crate::register_bitmasks!($valtype, $reg_desc, $(#[$inner])* $field, $offset, 1, []); )*
325        $crate::register_bitmasks!(@debug $valtype, $reg_mod, $reg_desc, [$($field),*]);
326    };
327
328    {
329        // BITFIELD_NAME OFFSET
330        // All fields are 1 bit
331        $(#[$outer:meta])*
332        $valtype:ident, $reg_mod:ident, $reg_desc:ident, [
333            $( $(#[$inner:meta])* $field:ident $offset:expr ),+ $(,)?
334        ]
335    } => {
336        $(#[$outer])*
337        $( $crate::register_bitmasks!($valtype, $reg_desc, $(#[$inner])* $field, $offset, 1, []); )*
338        $crate::register_bitmasks!(@debug $valtype, $reg_mod, $reg_desc, [$($field),*]);
339    };
340
341    {
342        // BITFIELD_NAME OFFSET(x) NUMBITS(y)
343        $(#[$outer:meta])*
344        $valtype:ident, $reg_mod:ident, $reg_desc:ident, [
345            $( $(#[$inner:meta])* $field:ident OFFSET($offset:expr) NUMBITS($numbits:expr) ),+ $(,)?
346        ]
347    } => {
348        $(#[$outer])*
349        $( $crate::register_bitmasks!($valtype, $reg_desc, $(#[$inner])* $field, $offset, $numbits, []); )*
350        $crate::register_bitmasks!(@debug $valtype, $reg_mod, $reg_desc, [$($field),*]);
351    };
352
353    {
354        // BITFIELD_NAME OFFSET(x) NUMBITS(y) []
355        $(#[$outer:meta])*
356        $valtype:ident, $reg_mod:ident, $reg_desc:ident, [
357            $( $(#[$inner:meta])* $field:ident OFFSET($offset:expr) NUMBITS($numbits:expr)
358               $values:tt ),+ $(,)?
359        ]
360    } => {
361        $(#[$outer])*
362        $( $crate::register_bitmasks!($valtype, $reg_desc, $(#[$inner])* $field, $offset, $numbits,
363                              $values); )*
364        $crate::register_bitmasks!(@debug $valtype, $reg_mod, $reg_desc, [$($field),*]);
365    };
366
367    {
368        $valtype:ident, $reg_desc:ident, $(#[$outer:meta])* $field:ident,
369                    $offset:expr, $numbits:expr,
370                    [$( $(#[$inner:meta])* $valname:ident = $value:expr ),+ $(,)?]
371    } => {
372        // this match arm is duplicated below with an allowance for 0 elements
373        // in the valname -> value array, to separately support the case of
374        // zero-variant enums not supporting non-default
375        // representations.
376        #[allow(non_upper_case_globals)]
377        #[allow(unused)]
378        pub const $field: Field<$valtype, $reg_desc> =
379            Field::<$valtype, $reg_desc>::new($crate::bitmask!($numbits), $offset);
380
381        #[allow(non_snake_case)]
382        #[allow(unused)]
383        $(#[$outer])*
384        pub mod $field {
385            #[allow(unused_imports)]
386            use $crate::fields::{TryFromValue, FieldValue};
387            use super::$reg_desc;
388
389            $(
390            #[allow(non_upper_case_globals)]
391            #[allow(unused)]
392            $(#[$inner])*
393            pub const $valname: FieldValue<$valtype, $reg_desc> =
394                FieldValue::<$valtype, $reg_desc>::new($crate::bitmask!($numbits),
395                    $offset, $value);
396            )*
397
398            #[allow(non_upper_case_globals)]
399            #[allow(unused)]
400            pub const SET: FieldValue<$valtype, $reg_desc> =
401                FieldValue::<$valtype, $reg_desc>::new($crate::bitmask!($numbits),
402                    $offset, $crate::bitmask!($numbits));
403
404            #[allow(non_upper_case_globals)]
405            #[allow(unused)]
406            pub const CLEAR: FieldValue<$valtype, $reg_desc> =
407                FieldValue::<$valtype, $reg_desc>::new($crate::bitmask!($numbits),
408                    $offset, 0);
409
410            #[allow(dead_code)]
411            #[allow(non_camel_case_types)]
412            #[derive(Copy, Clone, Debug, Eq, PartialEq)]
413            #[repr($valtype)] // so that values larger than isize::MAX can be stored
414            $(#[$outer])*
415            pub enum Value {
416                $(
417                    $(#[$inner])*
418                    $valname = $value,
419                )*
420            }
421
422            impl TryFromValue<$valtype> for Value {
423                type EnumType = Value;
424
425                fn try_from_value(v: $valtype) -> Option<Self::EnumType> {
426                    match v {
427                        $(
428                            $(#[$inner])*
429                            x if x == Value::$valname as $valtype => Some(Value::$valname),
430                        )*
431
432                        _ => Option::None
433                    }
434                }
435            }
436
437            impl From<Value> for FieldValue<$valtype, $reg_desc> {
438                fn from(v: Value) -> Self {
439                    Self::new($crate::bitmask!($numbits), $offset, v as $valtype)
440                }
441            }
442        }
443    };
444    {
445        $valtype:ident, $reg_desc:ident, $(#[$outer:meta])* $field:ident,
446                    $offset:expr, $numbits:expr,
447                    []
448    } => {
449        // same pattern as previous match arm, for 0 elements in array. Removes
450        // code associated with array.
451        #[allow(non_upper_case_globals)]
452        #[allow(unused)]
453        pub const $field: Field<$valtype, $reg_desc> =
454            Field::<$valtype, $reg_desc>::new($crate::bitmask!($numbits), $offset);
455
456        #[allow(non_snake_case)]
457        #[allow(unused)]
458        $(#[$outer])*
459        pub mod $field {
460            #[allow(unused_imports)]
461            use $crate::fields::{FieldValue, TryFromValue};
462            use super::$reg_desc;
463
464            #[allow(non_upper_case_globals)]
465            #[allow(unused)]
466            pub const SET: FieldValue<$valtype, $reg_desc> =
467                FieldValue::<$valtype, $reg_desc>::new($crate::bitmask!($numbits),
468                    $offset, $crate::bitmask!($numbits));
469
470            #[allow(non_upper_case_globals)]
471            #[allow(unused)]
472            pub const CLEAR: FieldValue<$valtype, $reg_desc> =
473                FieldValue::<$valtype, $reg_desc>::new($crate::bitmask!($numbits),
474                    $offset, 0);
475
476            #[allow(dead_code)]
477            #[allow(non_camel_case_types)]
478            #[derive(Debug)]
479            $(#[$outer])*
480            pub enum Value {}
481
482            impl TryFromValue<$valtype> for Value {
483                type EnumType = Value;
484
485                fn try_from_value(_v: $valtype) -> Option<Self::EnumType> {
486                    Option::None
487                }
488            }
489        }
490    };
491
492    // Implement the `RegisterDebugInfo` trait for the register. Refer to its
493    // documentation for more information on the individual types and fields.
494    (
495        // final implementation of the macro
496        @debug $valtype:ident, $reg_mod:ident, $reg_desc:ident, [$($field:ident),*]
497    ) => {
498        impl $crate::debug::RegisterDebugInfo<$valtype> for $reg_desc {
499            // Sequence of field value enum types (implementing `TryFromValue`,
500            // produced above), generated by recursing over the fields:
501            type FieldValueEnumTypes = $crate::register_bitmasks!(
502                @fv_enum_type_seq $valtype, $($field::Value),*
503            );
504
505            fn name() -> &'static str {
506                stringify!($reg_mod)
507            }
508
509            fn field_names() -> &'static [&'static str] {
510                &[
511                    $(
512                        stringify!($field)
513                    ),*
514                ]
515            }
516
517            fn fields() -> &'static [Field<$valtype, Self>] {
518                &[
519                    $(
520                        $field
521                    ),*
522                ]
523            }
524        }
525    };
526
527    // Build the recursive `FieldValueEnumSeq` type sequence. This will generate
528    // a type signature of the form:
529    //
530    // ```
531    // FieldValueEnumCons<u32, Foo,
532    //     FieldValueEnumCons<u32, Bar,
533    //         FieldValueEnumCons<u32, Baz,
534    //             FieldValueEnumNil
535    //         >
536    //     >
537    // >
538    // ```
539    (
540        @fv_enum_type_seq $valtype:ident, $enum_val:path $(, $($rest:path),+)?
541    ) => {
542        $crate::debug::FieldValueEnumCons<
543            $valtype,
544            $enum_val,
545            $crate::register_bitmasks!(@fv_enum_type_seq $valtype $(, $($rest),*)*)
546        >
547    };
548    (
549        @fv_enum_type_seq $valtype:ident $(,)?
550    ) => {
551        $crate::debug::FieldValueEnumNil
552    };
553}
554
555/// Define register types and fields.
556///
557/// Implementations of memory-mapped registers can use this macro to define the
558/// structure and bitwise meaning of individual registers in the peripheral. An
559/// example use for a hypothetical UART driver might look like:
560///
561/// ```rust,ignore
562/// register_bitfields![u32,
563///     CONTROL [
564///         ENABLE OFFSET(0) NUMBITS(1),
565///         STOP_BITS OFFSET(1) NUMBITS(2) [
566///             StopBits1 = 0,
567///             StopBits2 = 1,
568///             StopBits0 = 2
569///         ]
570///     ],
571///     BYTE [
572///         CHARACTER OFFSET(0) NUMBITS(8)
573///     ],
574///     INTERRUPT [
575///         TRANSMITTED OFFSET(0) NUMBITS(1),
576///         RECEIVED OFFSET(1) NUMBITS(1),
577///         FIFO_FULL OFFSET(2) NUMBITS(1)
578///     ]
579/// ];
580/// ```
581///
582/// Each field in the register can be identified by its offset within the
583/// register and its bitwidth. Fields that have discrete options with semantic
584/// meaning can be enumerated.
585#[macro_export]
586macro_rules! register_bitfields {
587    {
588        $valtype:ident, $( $(#[$inner:meta])* $vis:vis $reg:ident $fields:tt ),* $(,)?
589    } => {
590        $(
591            #[allow(non_snake_case)]
592            $(#[$inner])*
593            $vis mod $reg {
594                // Visibility note: This is left always `pub` as it is not
595                // meaningful to restrict access to the `Register` element of
596                // the register module if the module itself is in scope
597                //
598                // (if you can access $reg, you can access $reg::Register)
599                #[derive(Clone, Copy)]
600                pub struct Register;
601                impl $crate::RegisterLongName for Register {}
602
603                use $crate::fields::Field;
604
605                $crate::register_bitmasks!( $valtype, $reg, Register, $fields );
606            }
607        )*
608    }
609}
610
611#[cfg(test)]
612mod tests {
613    #[derive(Debug, PartialEq, Eq)]
614    enum Foo {
615        Foo0,
616        Foo1,
617        Foo2,
618        Foo3,
619        Foo4,
620        Foo5,
621        Foo6,
622        Foo7,
623    }
624
625    impl crate::fields::TryFromValue<u16> for Foo {
626        type EnumType = Foo;
627
628        fn try_from_value(v: u16) -> Option<Self::EnumType> {
629            Self::try_from_value(v as u32)
630        }
631    }
632    impl crate::fields::TryFromValue<u32> for Foo {
633        type EnumType = Foo;
634
635        fn try_from_value(v: u32) -> Option<Self::EnumType> {
636            match v {
637                0 => Some(Foo::Foo0),
638                1 => Some(Foo::Foo1),
639                2 => Some(Foo::Foo2),
640                3 => Some(Foo::Foo3),
641                4 => Some(Foo::Foo4),
642                5 => Some(Foo::Foo5),
643                6 => Some(Foo::Foo6),
644                7 => Some(Foo::Foo7),
645                _ => None,
646            }
647        }
648    }
649
650    mod field {
651        use super::Foo;
652        use crate::fields::{Field, TryFromValue};
653
654        #[test]
655        fn test_new() {
656            let field8 = Field::<u8, ()>::new(0x12, 3);
657            assert_eq!(field8.mask, 0x12_u8);
658            assert_eq!(field8.shift, 3);
659            let field16 = Field::<u16, ()>::new(0x1234, 5);
660            assert_eq!(field16.mask, 0x1234_u16);
661            assert_eq!(field16.shift, 5);
662            let field32 = Field::<u32, ()>::new(0x12345678, 9);
663            assert_eq!(field32.mask, 0x12345678_u32);
664            assert_eq!(field32.shift, 9);
665            let field64 = Field::<u64, ()>::new(0x12345678_9abcdef0, 1);
666            assert_eq!(field64.mask, 0x12345678_9abcdef0_u64);
667            assert_eq!(field64.shift, 1);
668            let field128 = Field::<u128, ()>::new(0x12345678_9abcdef0_0fedcba9_87654321, 1);
669            assert_eq!(field128.mask, 0x12345678_9abcdef0_0fedcba9_87654321_u128);
670            assert_eq!(field128.shift, 1);
671        }
672
673        #[test]
674        fn test_read() {
675            let field = Field::<u32, ()>::new(0xFF, 4);
676            assert_eq!(field.read(0x123), 0x12);
677            let field = Field::<u32, ()>::new(0xF0F, 4);
678            assert_eq!(field.read(0x1234), 0x103);
679        }
680
681        #[test]
682        fn test_is_set() {
683            let field = Field::<u16, ()>::new(0xFF, 4);
684            assert_eq!(field.is_set(0), false);
685            assert_eq!(field.is_set(0xFFFF), true);
686            assert_eq!(field.is_set(0x0FF0), true);
687            assert_eq!(field.is_set(0x1000), false);
688            assert_eq!(field.is_set(0x0100), true);
689            assert_eq!(field.is_set(0x0010), true);
690            assert_eq!(field.is_set(0x0001), false);
691
692            for shift in 0..24 {
693                let field = Field::<u32, ()>::new(0xFF, shift);
694                for x in 1..=0xFF {
695                    assert_eq!(field.is_set(x << shift), true);
696                }
697                assert_eq!(field.is_set(!(0xFF << shift)), false);
698            }
699        }
700
701        #[test]
702        fn test_read_as_enum() {
703            let field = Field::<u16, ()>::new(0x7, 4);
704            assert_eq!(field.read_as_enum(0x1234), Some(Foo::Foo3));
705            assert_eq!(field.read_as_enum(0x5678), Some(Foo::Foo7));
706            assert_eq!(field.read_as_enum(0xFFFF), Some(Foo::Foo7));
707            assert_eq!(field.read_as_enum(0x0000), Some(Foo::Foo0));
708            assert_eq!(field.read_as_enum(0x0010), Some(Foo::Foo1));
709            assert_eq!(field.read_as_enum(0x1204), Some(Foo::Foo0));
710
711            for shift in 0..29 {
712                let field = Field::<u32, ()>::new(0x7, shift);
713                for x in 0..8 {
714                    assert_eq!(field.read_as_enum(x << shift), Foo::try_from_value(x));
715                }
716            }
717        }
718    }
719
720    mod field_value {
721        use crate::fields::Field;
722
723        #[test]
724        fn test_from() {
725            let field = Field::<u32, ()>::new(0xFF, 4);
726            assert_eq!(u32::from(field.val(0)), 0);
727            assert_eq!(u32::from(field.val(0xFFFFFFFF)), 0xFF0);
728            assert_eq!(u32::from(field.val(0x12)), 0x120);
729            assert_eq!(u32::from(field.val(0x123)), 0x230);
730
731            for shift in 0..32 {
732                let field = Field::<u32, ()>::new(0xFF, shift);
733                for x in 0..=0xFF {
734                    assert_eq!(u32::from(field.val(x)), x << shift);
735                }
736            }
737        }
738
739        #[test]
740        fn test_read_same_field() {
741            let field = Field::<u32, ()>::new(0xFF, 4);
742            assert_eq!(field.val(0).read(field), 0);
743            assert_eq!(field.val(0xFFFFFFFF).read(field), 0xFF);
744            assert_eq!(field.val(0x12).read(field), 0x12);
745            assert_eq!(field.val(0x123).read(field), 0x23);
746
747            for shift in 0..24 {
748                let field = Field::<u32, ()>::new(0xFF, shift);
749                for x in 0..=0xFF {
750                    assert_eq!(field.val(x).read(field), x);
751                }
752            }
753        }
754
755        #[test]
756        fn test_read_disjoint_fields() {
757            for shift in 0..24 {
758                let field1 = Field::<u32, ()>::new(0xF0, shift);
759                let field2 = Field::<u32, ()>::new(0x0F, shift);
760                for x in 0..=0xFF {
761                    assert_eq!(field1.val(x).read(field2), 0);
762                    assert_eq!(field2.val(x).read(field1), 0);
763                }
764            }
765            for shift in 0..24 {
766                let field1 = Field::<u32, ()>::new(0xF, shift);
767                let field2 = Field::<u32, ()>::new(0xF, shift + 4);
768                for x in 0..=0xFF {
769                    assert_eq!(field1.val(x).read(field2), 0);
770                    assert_eq!(field2.val(x).read(field1), 0);
771                }
772            }
773        }
774
775        #[test]
776        fn test_modify() {
777            let field = Field::<u32, ()>::new(0xFF, 4);
778            assert_eq!(field.val(0x23).modify(0x0000), 0x0230);
779            assert_eq!(field.val(0x23).modify(0xFFFF), 0xF23F);
780            assert_eq!(field.val(0x23).modify(0x1234), 0x1234);
781            assert_eq!(field.val(0x23).modify(0x5678), 0x5238);
782        }
783
784        #[test]
785        fn test_any_matching_bits_set() {
786            let field = Field::<u32, ()>::new(0xFF, 4);
787            assert_eq!(field.val(0x23).any_matching_bits_set(0x1234), true);
788            assert_eq!(field.val(0x23).any_matching_bits_set(0x5678), true);
789            assert_eq!(field.val(0x23).any_matching_bits_set(0x5008), false);
790
791            for shift in 0..24 {
792                let field = Field::<u32, ()>::new(0xFF, shift);
793                let field_value = field.val(0xff);
794                for y in 1..=0xff {
795                    assert_eq!(field_value.any_matching_bits_set(y << shift), true,);
796                }
797                assert_eq!(field_value.any_matching_bits_set(0), false);
798                assert_eq!(field_value.any_matching_bits_set(!(0xFF << shift)), false);
799            }
800        }
801
802        #[test]
803        fn test_matches_all() {
804            let field = Field::<u32, ()>::new(0xFF, 4);
805            assert_eq!(field.val(0x23).matches_all(0x1234), true);
806            assert_eq!(field.val(0x23).matches_all(0x5678), false);
807
808            for shift in 0..24 {
809                let field = Field::<u32, ()>::new(0xFF, shift);
810                for x in 0..=0xFF {
811                    assert_eq!(field.val(x).matches_all(x << shift), true);
812                    assert_eq!(field.val(x + 1).matches_all(x << shift), false);
813                }
814            }
815        }
816
817        #[test]
818        fn test_matches_any() {
819            register_bitfields! {
820                u32,
821
822                TEST [
823                    FLAG OFFSET(18) NUMBITS(1) [],
824                    SIZE OFFSET(0) NUMBITS(2) [
825                        Byte = 0,
826                        Halfword = 1,
827                        Word = 2
828                    ],
829                ]
830            }
831
832            let value: crate::LocalRegisterCopy<u32, TEST::Register> =
833                crate::LocalRegisterCopy::new(2);
834            assert!(value.matches_any(&[TEST::SIZE::Word]));
835            assert!(!value.matches_any(&[TEST::SIZE::Halfword]));
836            assert!(!value.matches_any(&[TEST::SIZE::Byte]));
837            assert!(value.matches_any(&[TEST::SIZE::Word, TEST::FLAG::SET]));
838            assert!(value.matches_any(&[TEST::SIZE::Halfword, TEST::FLAG::CLEAR]));
839            assert!(!value.matches_any(&[TEST::SIZE::Halfword, TEST::FLAG::SET]));
840            let value: crate::LocalRegisterCopy<u32, TEST::Register> =
841                crate::LocalRegisterCopy::new(266241);
842            assert!(value.matches_any(&[TEST::FLAG::SET]));
843            assert!(!value.matches_any(&[TEST::FLAG::CLEAR]));
844        }
845
846        #[test]
847        fn test_add_disjoint_fields() {
848            let field1 = Field::<u32, ()>::new(0xFF, 24);
849            let field2 = Field::<u32, ()>::new(0xFF, 16);
850            let field3 = Field::<u32, ()>::new(0xFF, 8);
851            let field4 = Field::<u32, ()>::new(0xFF, 0);
852            assert_eq!(
853                u32::from(
854                    field1.val(0x12) + field2.val(0x34) + field3.val(0x56) + field4.val(0x78)
855                ),
856                0x12345678
857            );
858
859            for shift in 0..24 {
860                let field1 = Field::<u32, ()>::new(0xF, shift);
861                let field2 = Field::<u32, ()>::new(0xF, shift + 4);
862                for x in 0..=0xF {
863                    for y in 0..=0xF {
864                        assert_eq!(
865                            u32::from(field1.val(x) + field2.val(y)),
866                            (x | (y << 4)) << shift
867                        );
868                    }
869                }
870            }
871        }
872
873        #[test]
874        fn test_add_assign_disjoint_fields() {
875            let field1 = Field::<u32, ()>::new(0xFF, 24);
876            let field2 = Field::<u32, ()>::new(0xFF, 16);
877            let field3 = Field::<u32, ()>::new(0xFF, 8);
878            let field4 = Field::<u32, ()>::new(0xFF, 0);
879
880            let mut value = field1.val(0x12);
881            value += field2.val(0x34);
882            value += field3.val(0x56);
883            value += field4.val(0x78);
884            assert_eq!(u32::from(value), 0x12345678);
885
886            for shift in 0..24 {
887                let field1 = Field::<u32, ()>::new(0xF, shift);
888                let field2 = Field::<u32, ()>::new(0xF, shift + 4);
889                for x in 0..=0xF {
890                    for y in 0..=0xF {
891                        let mut value = field1.val(x);
892                        value += field2.val(y);
893                        assert_eq!(u32::from(value), (x | (y << 4)) << shift);
894                    }
895                }
896            }
897        }
898    }
899
900    // TODO: More unit tests here.
901}