1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2022.

//! Interfaces (traits) to register types
//!
//! This module contains traits which reflect standardized interfaces
//! to different types of registers. Examples of registers
//! implementing these interfaces are [`ReadWrite`](crate::registers::ReadWrite) or
//! [`InMemoryRegister`](crate::registers::InMemoryRegister).
//!
//! Each trait has two associated type parameters, namely:
//!
//! - `T`: [`UIntLike`], indicating the underlying
//!   integer type used to represent the register's raw contents.
//!
//! - `R`: [`RegisterLongName`], functioning
//!   as a type to identify this register's descriptive name and
//!   semantic meaning. It is further used to impose type constraints
//!   on values passed through the API, such as
//!   [`FieldValue`].
//!
//! Registers can have different access levels, which are mapped to
//! different traits respectively:
//!
//! - [`Readable`]: indicates that the current value of this register
//!   can be read. Implementations will need to provide the
//!   [`get`](crate::interfaces::Readable::get) method.
//!
//! - [`Writeable`]: indicates that the value of this register can be
//!   set. Implementations will need to provide the
//!   [`set`](crate::interfaces::Writeable::set) method.
//!
//! - [`ReadWriteable`]: indicates that this register can be
//!   _modified_. It is not sufficient for registers to be both read-
//!   and writable, they must also have the same semantic meaning when
//!   read from and written to. This is not true in general, for
//!   example a memory-mapped UART register might transmit when
//!   writing and receive when reading.
//!
//!   If a type implements both [`Readable`] and [`Writeable`], and
//!   the associated [`RegisterLongName`]
//!   type parameters are identical, it will automatically implement
//!   [`ReadWriteable`]. In particular, for
//!   [`Aliased`](crate::registers::Aliased) this is -- in general --
//!   not the case, so
//!
//!   ```rust
//!   # use tock_registers::interfaces::{Readable, Writeable, ReadWriteable};
//!   # use tock_registers::registers::ReadWrite;
//!   # use tock_registers::register_bitfields;
//!   register_bitfields![u8,
//!       A [
//!           DUMMY OFFSET(0) NUMBITS(1) [],
//!       ],
//!   ];
//!   let mut register_memory: u8 = 0;
//!   let read_write_reg: &ReadWrite<u8, A::Register> = unsafe {
//!       core::mem::transmute(&mut register_memory)
//!   };
//!   ReadWriteable::modify(read_write_reg, A::DUMMY::SET);
//!   ```
//!
//!   works, but not
//!
//!   ```compile_fail
//!   # use tock_registers::interfaces::{Readable, Writeable, ReadWriteable};
//!   # use tock_registers::registers::Aliased;
//!   # use tock_registers::register_bitfields;
//!   register_bitfields![u8,
//!       A [
//!           DUMMY OFFSET(0) NUMBITS(1) [],
//!       ],
//!       B [
//!           DUMMY OFFSET(0) NUMBITS(1) [],
//!       ],
//!   ];
//!   let aliased_reg: &Aliased<u8, A::Register, B::Register> = unsafe {
//!       core::mem::transmute(Box::leak(Box::new(0_u8)))
//!   };
//!   ReadWriteable::modify(aliased_reg, A::DUMMY::SET);
//!   ```
//!
//! - [`Debuggable`]: indicates that the register supports producing
//!   human-readable debug output using the `RegisterDebugValue` type.
//!   This type can be produced with the
//!   [`debug`](crate::interfaces::Debuggable::debug) method.  This
//!   will return a value that implements [`Debug`](core::fmt::Debug).
//!   It is automticaly implemented for any register implementing
//!   [`Readable`].
//!
//!
//! ## Example: implementing a custom register type
//!
//! These traits can be used to implement custom register types, which
//! are compatible to the ones shipped in this crate. For example, to
//! define a register which sets a `u8` value using a Cell reference,
//! always reads the bitwise-negated vale and prints every written
//! value to the console:
//!
//! ```rust
//! # use core::cell::Cell;
//! # use core::marker::PhantomData;
//! #
//! # use tock_registers::interfaces::{Readable, Writeable, ReadWriteable};
//! # use tock_registers::RegisterLongName;
//! # use tock_registers::register_bitfields;
//! #
//! struct DummyRegister<'a, R: RegisterLongName> {
//!     cell_ref: &'a Cell<u8>,
//!     _register_long_name: PhantomData<R>,
//! }
//!
//! impl<'a, R: RegisterLongName> Readable for DummyRegister<'a, R> {
//!     type T = u8;
//!     type R = R;
//!
//!     fn get(&self) -> u8 {
//!         // Return the bitwise-inverse of the current value
//!         !self.cell_ref.get()
//!     }
//! }
//!
//! impl<'a, R: RegisterLongName> Writeable for DummyRegister<'a, R> {
//!     type T = u8;
//!     type R = R;
//!
//!     fn set(&self, value: u8) {
//!         println!("Setting Cell to {:02x?}!", value);
//!         self.cell_ref.set(value);
//!     }
//! }
//!
//! register_bitfields![u8,
//!     DummyReg [
//!         HIGH OFFSET(4) NUMBITS(4) [
//!             A = 0b0001,
//!             B = 0b0010,
//!             C = 0b0100,
//!             D = 0b1000,
//!         ],
//!         LOW OFFSET(0) NUMBITS(4) [],
//!     ],
//! ];
//!
//! // Create a new DummyRegister over some Cell<u8>
//! let cell = Cell::new(0);
//! let dummy = DummyRegister {
//!     cell_ref: &cell,
//!     _register_long_name: PhantomData,
//! };
//!
//! // Set a value and read it back. This demonstrates the raw getters
//! // and setters of Writeable and Readable
//! dummy.set(0xFA);
//! assert!(dummy.get() == 0x05);
//!
//! // Use some of the automatically derived APIs, such as
//! // ReadWriteable::modify and Readable::read
//! dummy.modify(DummyReg::HIGH::C);
//! assert!(dummy.read(DummyReg::HIGH) == 0xb);
//! ```

use crate::fields::{Field, FieldValue, TryFromValue};
use crate::{LocalRegisterCopy, RegisterLongName, UIntLike};

/// Readable register
///
/// Register which at least supports reading the current value. Only
/// [`Readable::get`] must be implemented, as for other methods a
/// default implementation is provided.
///
/// A register that is both [`Readable`] and [`Writeable`] will also
/// automatically be [`ReadWriteable`], if the [`RegisterLongName`] of
/// [`Readable`] is the same as that of [`Writeable`] (i.e. not for
/// [`Aliased`](crate::registers::Aliased) registers).
pub trait Readable {
    type T: UIntLike;
    type R: RegisterLongName;

    /// Get the raw register value
    fn get(&self) -> Self::T;

    #[inline]
    /// Read the value of the given field
    fn read(&self, field: Field<Self::T, Self::R>) -> Self::T {
        field.read(self.get())
    }

    /// Set the raw register value
    ///
    /// The [`register_bitfields!`](crate::register_bitfields) macro will
    /// generate an enum containing the various named field variants and
    /// implementing the required [`TryFromValue`] trait. It is accessible as
    /// `$REGISTER_NAME::$FIELD_NAME::Value`.
    ///
    /// This method can be useful to symbolically represent read register field
    /// states throughout the codebase and to enforce exhaustive matches over
    /// all defined valid register field values.
    ///
    /// ## Usage Example
    ///
    /// ```rust
    /// # use tock_registers::interfaces::Readable;
    /// # use tock_registers::registers::InMemoryRegister;
    /// # use tock_registers::register_bitfields;
    /// register_bitfields![u8,
    ///     EXAMPLEREG [
    ///         TESTFIELD OFFSET(0) NUMBITS(2) [
    ///             Foo = 0,
    ///             Bar = 1,
    ///             Baz = 2,
    ///         ],
    ///     ],
    /// ];
    ///
    /// let reg: InMemoryRegister<u8, EXAMPLEREG::Register> =
    ///     InMemoryRegister::new(2);
    ///
    /// match reg.read_as_enum(EXAMPLEREG::TESTFIELD) {
    ///     Some(EXAMPLEREG::TESTFIELD::Value::Foo) => "Tock",
    ///     Some(EXAMPLEREG::TESTFIELD::Value::Bar) => "is",
    ///     Some(EXAMPLEREG::TESTFIELD::Value::Baz) => "awesome!",
    ///     None => panic!("boo!"),
    /// };
    /// ```
    #[inline]
    fn read_as_enum<E: TryFromValue<Self::T, EnumType = E>>(
        &self,
        field: Field<Self::T, Self::R>,
    ) -> Option<E> {
        field.read_as_enum(self.get())
    }

    #[inline]
    /// Make a local copy of the register
    fn extract(&self) -> LocalRegisterCopy<Self::T, Self::R> {
        LocalRegisterCopy::new(self.get())
    }

    #[inline]
    /// Check if one or more bits in a field are set
    fn is_set(&self, field: Field<Self::T, Self::R>) -> bool {
        field.is_set(self.get())
    }

    /// Check if any bits corresponding to the mask in the passed `FieldValue` are set.
    /// This function is identical to `is_set()` but operates on a `FieldValue` rather
    /// than a `Field`, allowing for checking if any bits are set across multiple,
    /// non-contiguous portions of a bitfield.
    #[inline]
    fn any_matching_bits_set(&self, field: FieldValue<Self::T, Self::R>) -> bool {
        field.any_matching_bits_set(self.get())
    }

    #[inline]
    /// Check if all specified parts of a field match
    fn matches_all(&self, field: FieldValue<Self::T, Self::R>) -> bool {
        field.matches_all(self.get())
    }

    /// Check if any of the passed parts of a field exactly match the contained
    /// value. This allows for matching on unset bits, or matching on specific values
    /// in multi-bit fields.
    #[inline]
    fn matches_any(&self, fields: &[FieldValue<Self::T, Self::R>]) -> bool {
        fields
            .iter()
            .any(|field| self.get() & field.mask() == field.value)
    }
}

/// [`Debuggable`] is a trait for registers that support human-readable debug
/// output with [`core::fmt::Debug`].  It extends the [`Readable`] trait and
/// doesn't require manual implementation.
///
/// This is implemented for the register when using the [`register_bitfields`] macro.
///
/// The `debug` method returns a value that implements [`core::fmt::Debug`].
///
/// [`register_bitfields`]: crate::register_bitfields
pub trait Debuggable: Readable {
    /// Returns a [`RegisterDebugValue`](crate::debug::RegisterDebugValue) that
    /// implements [`core::fmt::Debug`], the debug information is extracted from
    /// `<Register>::DebugInfo`.
    #[inline]
    fn debug(&self) -> crate::debug::RegisterDebugValue<Self::T, Self::R>
    where
        Self::R: crate::debug::RegisterDebugInfo<Self::T>,
    {
        crate::debug::RegisterDebugValue {
            data: self.get(),
            _reg: core::marker::PhantomData,
        }
    }
}

// pass Readable implementation to Debuggable
impl<T: Readable> Debuggable for T {}

/// Writeable register
///
/// Register which at least supports setting a value. Only
/// [`Writeable::set`] must be implemented, as for other methods a
/// default implementation is provided.
///
/// A register that is both [`Readable`] and [`Writeable`] will also
/// automatically be [`ReadWriteable`], if the [`RegisterLongName`] of
/// [`Readable`] is the same as that of [`Writeable`] (i.e. not for
/// [`Aliased`](crate::registers::Aliased) registers).
pub trait Writeable {
    type T: UIntLike;
    type R: RegisterLongName;

    /// Set the raw register value
    fn set(&self, value: Self::T);

    #[inline]
    /// Write the value of one or more fields, overwriting the other fields with zero
    fn write(&self, field: FieldValue<Self::T, Self::R>) {
        self.set(field.value);
    }

    #[inline]
    /// Write the value of one or more fields, maintaining the value of unchanged fields via a
    /// provided original value, rather than a register read.
    fn modify_no_read(
        &self,
        original: LocalRegisterCopy<Self::T, Self::R>,
        field: FieldValue<Self::T, Self::R>,
    ) {
        self.set(field.modify(original.get()));
    }
}

/// [`Readable`] and [`Writeable`] register, over the same
/// [`RegisterLongName`]
///
/// Register which supports both reading and setting a value.
///
/// **This trait does not have to be implemented manually!** It is
/// automatically implemented for every type that is both [`Readable`]
/// and [`Writeable`], as long as [`Readable::R`] == [`Writeable::R`]
/// (i.e. not for [`Aliased`](crate::registers::Aliased) registers).
pub trait ReadWriteable {
    type T: UIntLike;
    type R: RegisterLongName;

    /// Write the value of one or more fields, leaving the other fields unchanged
    fn modify(&self, field: FieldValue<Self::T, Self::R>);
}

impl<T: UIntLike, R: RegisterLongName, S> ReadWriteable for S
where
    S: Readable<T = T, R = R> + Writeable<T = T, R = R>,
{
    type T = T;
    type R = R;

    #[inline]
    fn modify(&self, field: FieldValue<Self::T, Self::R>) {
        self.set(field.modify(self.get()));
    }
}