irv_traits/
lib.rs

1/// An error that can be thrown on a memory access.
2#[derive(Debug)]
3pub enum BusError {
4    /// The address is invalid (but well-aligned).
5    AccessFault,
6    /// The address is misaligned.
7    AddressMisaligned,
8}
9
10/// A bus facilitating accesses on the emulated physical bus.
11pub trait Bus<A, V> {
12    /// Loads the value located at the given `address`.
13    fn load(&self, address: A) -> Result<V, BusError>;
14    /// Stores the given `value` to the given `address`.
15    fn store(&self, address: A, value: V) -> Result<(), BusError>;
16}
17
18/// A bus facilitating accesses to the emulated CSRs.
19pub trait Csr {
20    /// Attempts to access the CSR at the given `address` by setting the value
21    /// of the CSR to the result of calling `f` with its current value.
22    ///
23    /// Returns the original value of the CSR on success.
24    ///
25    /// Returns `Err(CsrIllegal)` when the access is illegal for some reason,
26    /// usually because the CSR does not exist or because the current privilege
27    /// level does not have access.
28    fn access(
29        &mut self,
30        address: CsrAddress,
31        f: impl FnOnce(u64) -> u64,
32    ) -> Result<u64, CsrIllegal>;
33}
34
35/// Returned by [Csr::access] to indicate an illegal CSR access.
36pub struct CsrIllegal;
37
38/// A wrapper for integers guaranteed to be less than 4096 that is used to represent
39/// CSR addresses.
40#[derive(Clone, Copy)]
41pub struct CsrAddress(u16);
42
43impl Csr for () {
44    fn access(&mut self, address: CsrAddress, f: impl FnOnce(u64) -> u64) -> Result<u64, CsrIllegal> {
45        Err(CsrIllegal)
46    }
47}
48
49impl CsrAddress {
50    /// Creates a new CsrAddress if the given address is less than 4096.
51    pub const fn new(address: u16) -> Option<CsrAddress> {
52        if address < 4096 {
53            Some(CsrAddress(address))
54        } else {
55            None
56        }
57    }
58
59    /// Creates a new CsrAddress and assumes that the given address is less than 4096.
60    /// 
61    /// # Safety
62    /// `address` must be less than 4096. If it is not, undefined behavior may be invoked,
63    /// because users of this type are permitted to assume that the interior address is
64    /// less than 4096. 
65    pub const unsafe fn new_unchecked(address: u16) -> CsrAddress {
66        CsrAddress(address)
67    }
68
69    /// Gets the actual address.
70    pub const fn address(self) -> u16 {
71        self.0
72    }
73}