Skip to content

Commit 4d4ef06

Browse files
committed
riscv: add fallible functions to mcounteren
Adds fallible access functions for `Mcounteren` HPM fields.
1 parent 573a8a5 commit 4d4ef06

File tree

1 file changed

+85
-1
lines changed

1 file changed

+85
-1
lines changed

riscv/src/register/mcounteren.rs

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! mcounteren register
22
33
use crate::bits::{bf_extract, bf_insert};
4+
use crate::result::{Error, Result};
45

56
/// mcounteren register
67
#[derive(Clone, Copy, Debug)]
@@ -58,6 +59,22 @@ impl Mcounteren {
5859
bf_extract(self.bits, index, 1) != 0
5960
}
6061

62+
/// Fallible Supervisor "hpm\[x\]" Enable (bits 3-31).
63+
///
64+
/// Attempts to read the "hpm\[x\]" value, and returns an error if the `index` is invalid.
65+
#[inline]
66+
pub fn try_hpm(&self, index: usize) -> Result<bool> {
67+
if (3..32).contains(&index) {
68+
Ok(bf_extract(self.bits, index, 1) != 0)
69+
} else {
70+
Err(Error::OutOfBounds {
71+
index,
72+
min: 3,
73+
max: 31,
74+
})
75+
}
76+
}
77+
6178
/// Sets whether to enable the "hpm\[X\]" counter.
6279
///
6380
/// Only updates the in-memory value, does not modify the `mcounteren` register.
@@ -66,6 +83,25 @@ impl Mcounteren {
6683
assert!((3..32).contains(&index));
6784
self.bits = bf_insert(self.bits, index, 1, hpm as usize);
6885
}
86+
87+
/// Sets whether to enable the "hpm\[X\]" counter.
88+
///
89+
/// Only updates the in-memory value, does not modify the `mcounteren` register.
90+
///
91+
/// Attempts to update the "hpm\[x\]" value, and returns an error if the `index` is invalid.
92+
#[inline]
93+
pub fn try_set_hpm(&mut self, index: usize, hpm: bool) -> Result<()> {
94+
if (3..32).contains(&index) {
95+
self.bits = bf_insert(self.bits, index, 1, hpm as usize);
96+
Ok(())
97+
} else {
98+
Err(Error::OutOfBounds {
99+
index,
100+
min: 3,
101+
max: 31,
102+
})
103+
}
104+
}
69105
}
70106

71107
read_csr_as!(Mcounteren, 0x306);
@@ -91,12 +127,38 @@ pub unsafe fn set_hpm(index: usize) {
91127
_set(1 << index);
92128
}
93129

130+
#[inline]
131+
pub unsafe fn try_set_hpm(index: usize) -> Result<()> {
132+
if (3..32).contains(&index) {
133+
_try_set(1 << index)
134+
} else {
135+
Err(Error::OutOfBounds {
136+
index,
137+
min: 3,
138+
max: 31,
139+
})
140+
}
141+
}
142+
94143
#[inline]
95144
pub unsafe fn clear_hpm(index: usize) {
96145
assert!((3..32).contains(&index));
97146
_clear(1 << index);
98147
}
99148

149+
#[inline]
150+
pub unsafe fn try_clear_hpm(index: usize) -> Result<()> {
151+
if (3..32).contains(&index) {
152+
_try_clear(1 << index)
153+
} else {
154+
Err(Error::OutOfBounds {
155+
index,
156+
min: 3,
157+
max: 31,
158+
})
159+
}
160+
}
161+
100162
#[cfg(test)]
101163
mod tests {
102164
use super::*;
@@ -131,12 +193,34 @@ mod tests {
131193

132194
(3..32).for_each(|i| {
133195
assert!(!m.hpm(i));
196+
assert_eq!(m.try_hpm(i), Ok(false));
134197

135198
m.set_hpm(i, true);
136199
assert!(m.hpm(i));
137200

138-
m.set_hpm(i, false);
201+
assert_eq!(m.try_set_hpm(i, false), Ok(()));
202+
assert_eq!(m.try_hpm(i), Ok(false));
203+
139204
assert!(!m.hpm(i));
140205
});
206+
207+
(0..3).chain(32..64).for_each(|index| {
208+
assert_eq!(
209+
m.try_hpm(index),
210+
Err(Error::OutOfBounds {
211+
index,
212+
min: 3,
213+
max: 31
214+
})
215+
);
216+
assert_eq!(
217+
m.try_set_hpm(index, false),
218+
Err(Error::OutOfBounds {
219+
index,
220+
min: 3,
221+
max: 31
222+
})
223+
);
224+
})
141225
}
142226
}

0 commit comments

Comments
 (0)