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