1
1
//! mcounteren register
2
2
3
3
use crate :: bits:: { bf_extract, bf_insert} ;
4
+ use crate :: result:: { Error , Result } ;
4
5
5
6
/// mcounteren register
6
7
#[ derive( Clone , Copy , Debug ) ]
@@ -52,19 +53,56 @@ impl Mcounteren {
52
53
}
53
54
54
55
/// Supervisor "hpm\[x\]" Enable (bits 3-31)
56
+ ///
57
+ /// **WARNING**: panics on `index` out-of-bounds
55
58
#[ inline]
56
59
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
+ }
59
77
}
60
78
61
79
/// Sets whether to enable the "hpm\[X\]" counter.
62
80
///
63
81
/// Only updates the in-memory value, does not modify the `mcounteren` register.
82
+ ///
83
+ /// **WARNING**: panics on `index` out-of-bounds
64
84
#[ inline]
65
85
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
+ }
68
106
}
69
107
}
70
108
@@ -85,16 +123,62 @@ set_clear_csr!(
85
123
/// Supervisor instret Enable
86
124
, set_ir, clear_ir, 1 << 2 ) ;
87
125
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
88
134
#[ inline]
89
135
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
+ }
92
153
}
93
154
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
94
163
#[ inline]
95
164
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
+ }
98
182
}
99
183
100
184
#[ cfg( test) ]
@@ -131,12 +215,34 @@ mod tests {
131
215
132
216
( 3 ..32 ) . for_each ( |i| {
133
217
assert ! ( !m. hpm( i) ) ;
218
+ assert_eq ! ( m. try_hpm( i) , Ok ( false ) ) ;
134
219
135
220
m. set_hpm ( i, true ) ;
136
221
assert ! ( m. hpm( i) ) ;
137
222
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
+
139
226
assert ! ( !m. hpm( i) ) ;
140
227
} ) ;
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
+ } )
141
247
}
142
248
}
0 commit comments