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}