//! Implement the Field structure. /// Structure representing the location of a register. /// This structure does not provide any kind of safety, it /// is only descriptif. /// /// Fields represent a continuous set of bits in an alligned /// `u32`. This means that the address is a multiple of 4, /// the offset is < 32, and offset + size <= 32. /// /// The constructor of the is class ensure that the field is /// always inside the `u32` at `address`, and that `address` /// is alligned. pub struct Field { /// The address of the discribed field. address: usize, /// The offset of the first bit of the field relative to the /// address. offset: usize, /// The size of the field in bit. size: usize, /// The mask for the field in the `u32` at `address`. mask: u32 } // TODO: test impl Field { /// Constructor for a Field. /// The field is defined by the `size` bits at `offset` bits after /// `address`. (**`address` is in bytes, not bits**) pub const fn new(address: usize, offset: usize, size: usize) -> Self { // align the address let offset = offset + 8 * (address % 4); let address = address - (address % 4); // make sure the field is in the u32 at address let address = address + 4 * (offset / 32); let offset = offset % 32; // make sure the field does not overlap with the next u32 if offset + size > 32 { panic!("A field can not overlap two aligned `u32`"); } let mask = Self::compute_mask(offset, size); Self { address, offset, size, mask } } /// Compute mask for the field. const fn compute_mask(offset: usize, size: usize) -> u32 { let mut mask = 0u32; // Const functions don't allow for loops. let mut i = 0; while i < size { mask <<= 1; mask |= 1; i += 1; } mask <<= offset; mask } /// Return the address of the `u32` containing the field. pub const fn get_address(&self) -> usize { self.address } /// Return the offset of the field in relation to the address, in bits. #[allow(dead_code)] pub const fn get_offset(&self) -> usize { self.offset } /// Return the size of the field in bit. #[allow(dead_code)] pub const fn get_size(&self) -> usize { self.size } /// Return the mask of the field in the `u32` at `address`. pub const fn get_mask(&self) -> u32 { self.mask } }