Skip to content

Commit 5165db3

Browse files
committed
riscv: add fallible functions to mcounteren
Adds fallible access functions for `Mcounteren` HPM fields.
1 parent 0d23dc1 commit 5165db3

File tree

1 file changed

+115
-9
lines changed

1 file changed

+115
-9
lines changed

riscv/src/register/mcounteren.rs

+115-9
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)]
@@ -52,19 +53,56 @@ impl Mcounteren {
5253
}
5354

5455
/// Supervisor "hpm\[x\]" Enable (bits 3-31)
56+
///
57+
/// **WARNING**: panics on `index` out-of-bounds
5558
#[inline]
5659
pub fn hpm(&self, index: usize) -> bool {
57-
assert!((3..32).contains(&index));
58-
bf_extract(self.bits, index, 1) != 0
60+
self.try_hpm(index).unwrap()
61+
}
62+
63+
/// Fallible Supervisor "hpm\[x\]" Enable (bits 3-31).
64+
///
65+
/// Attempts to read the "hpm\[x\]" value, and returns an error if the `index` is invalid.
66+
#[inline]
67+
pub fn try_hpm(&self, index: usize) -> Result<bool> {
68+
if (3..32).contains(&index) {
69+
Ok(bf_extract(self.bits, index, 1) != 0)
70+
} else {
71+
Err(Error::IndexOutOfBounds {
72+
index,
73+
min: 3,
74+
max: 31,
75+
})
76+
}
5977
}
6078

6179
/// Sets whether to enable the "hpm\[X\]" counter.
6280
///
6381
/// Only updates the in-memory value, does not modify the `mcounteren` register.
82+
///
83+
/// **WARNING**: panics on `index` out-of-bounds
6484
#[inline]
6585
pub fn set_hpm(&mut self, index: usize, hpm: bool) {
66-
assert!((3..32).contains(&index));
67-
self.bits = bf_insert(self.bits, index, 1, hpm as usize);
86+
self.try_set_hpm(index, hpm).unwrap()
87+
}
88+
89+
/// Sets whether to enable the "hpm\[X\]" counter.
90+
///
91+
/// Only updates the in-memory value, does not modify the `mcounteren` register.
92+
///
93+
/// Attempts to update the "hpm\[x\]" value, and returns an error if the `index` is invalid.
94+
#[inline]
95+
pub fn try_set_hpm(&mut self, index: usize, hpm: bool) -> Result<()> {
96+
if (3..32).contains(&index) {
97+
self.bits = bf_insert(self.bits, index, 1, hpm as usize);
98+
Ok(())
99+
} else {
100+
Err(Error::IndexOutOfBounds {
101+
index,
102+
min: 3,
103+
max: 31,
104+
})
105+
}
68106
}
69107
}
70108

@@ -85,16 +123,62 @@ set_clear_csr!(
85123
/// Supervisor instret Enable
86124
, set_ir, clear_ir, 1 << 2);
87125

126+
/// Enables the "hpm\[X\]" counter.
127+
///
128+
/// Updates the `mcounteren` register.
129+
///
130+
/// **WARNING**: panics on:
131+
///
132+
/// - non-`riscv` targets
133+
/// - `index` out-of-bounds
88134
#[inline]
89135
pub unsafe fn set_hpm(index: usize) {
90-
assert!((3..32).contains(&index));
91-
_set(1 << index);
136+
try_set_hpm(index).unwrap();
137+
}
138+
139+
/// Attempts to enable the "hpm\[X\]" counter.
140+
///
141+
/// Updates the `mcounteren` register.
142+
#[inline]
143+
pub unsafe fn try_set_hpm(index: usize) -> Result<()> {
144+
if (3..32).contains(&index) {
145+
_try_set(1 << index)
146+
} else {
147+
Err(Error::IndexOutOfBounds {
148+
index,
149+
min: 3,
150+
max: 31,
151+
})
152+
}
92153
}
93154

155+
/// Disables the "hpm\[X\]" counter.
156+
///
157+
/// Updates the `mcounteren` register.
158+
///
159+
/// **WARNING**: panics on:
160+
///
161+
/// - non-`riscv` targets
162+
/// - `index` out-of-bounds
94163
#[inline]
95164
pub unsafe fn clear_hpm(index: usize) {
96-
assert!((3..32).contains(&index));
97-
_clear(1 << index);
165+
try_clear_hpm(index).unwrap();
166+
}
167+
168+
/// Attempts to disable the "hpm\[X\]" counter.
169+
///
170+
/// Updates the `mcounteren` register.
171+
#[inline]
172+
pub unsafe fn try_clear_hpm(index: usize) -> Result<()> {
173+
if (3..32).contains(&index) {
174+
_try_clear(1 << index)
175+
} else {
176+
Err(Error::IndexOutOfBounds {
177+
index,
178+
min: 3,
179+
max: 31,
180+
})
181+
}
98182
}
99183

100184
#[cfg(test)]
@@ -131,12 +215,34 @@ mod tests {
131215

132216
(3..32).for_each(|i| {
133217
assert!(!m.hpm(i));
218+
assert_eq!(m.try_hpm(i), Ok(false));
134219

135220
m.set_hpm(i, true);
136221
assert!(m.hpm(i));
137222

138-
m.set_hpm(i, false);
223+
assert_eq!(m.try_set_hpm(i, false), Ok(()));
224+
assert_eq!(m.try_hpm(i), Ok(false));
225+
139226
assert!(!m.hpm(i));
140227
});
228+
229+
(0..3).chain(32..64).for_each(|index| {
230+
assert_eq!(
231+
m.try_hpm(index),
232+
Err(Error::IndexOutOfBounds {
233+
index,
234+
min: 3,
235+
max: 31
236+
})
237+
);
238+
assert_eq!(
239+
m.try_set_hpm(index, false),
240+
Err(Error::IndexOutOfBounds {
241+
index,
242+
min: 3,
243+
max: 31
244+
})
245+
);
246+
})
141247
}
142248
}

0 commit comments

Comments
 (0)