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,62 @@ impl Mcounteren {
52
53
}
53
54
54
55
/// Supervisor "hpm\[x\]" Enable (bits 3-31)
56
+ ///
57
+ /// **WARNING**: panics on:
58
+ ///
59
+ /// - non-`riscv` targets
60
+ /// - `index` out-of-bounds
55
61
#[ inline]
56
62
pub fn hpm ( & self , index : usize ) -> bool {
57
- assert ! ( ( 3 ..32 ) . contains( & index) ) ;
58
- bf_extract ( self . bits , index, 1 ) != 0
63
+ self . try_hpm ( index) . unwrap ( )
64
+ }
65
+
66
+ /// Fallible Supervisor "hpm\[x\]" Enable (bits 3-31).
67
+ ///
68
+ /// Attempts to read the "hpm\[x\]" value, and returns an error if the `index` is invalid.
69
+ #[ inline]
70
+ pub fn try_hpm ( & self , index : usize ) -> Result < bool > {
71
+ if ( 3 ..32 ) . contains ( & index) {
72
+ Ok ( bf_extract ( self . bits , index, 1 ) != 0 )
73
+ } else {
74
+ Err ( Error :: IndexOutOfBounds {
75
+ index,
76
+ min : 3 ,
77
+ max : 31 ,
78
+ } )
79
+ }
59
80
}
60
81
61
82
/// Sets whether to enable the "hpm\[X\]" counter.
62
83
///
63
84
/// Only updates the in-memory value, does not modify the `mcounteren` register.
85
+ ///
86
+ /// **WARNING**: panics on:
87
+ ///
88
+ /// - non-`riscv` targets
89
+ /// - `index` out-of-bounds
64
90
#[ inline]
65
91
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 ) ;
92
+ self . try_set_hpm ( index, hpm) . unwrap ( )
93
+ }
94
+
95
+ /// Sets whether to enable the "hpm\[X\]" counter.
96
+ ///
97
+ /// Only updates the in-memory value, does not modify the `mcounteren` register.
98
+ ///
99
+ /// Attempts to update the "hpm\[x\]" value, and returns an error if the `index` is invalid.
100
+ #[ inline]
101
+ pub fn try_set_hpm ( & mut self , index : usize , hpm : bool ) -> Result < ( ) > {
102
+ if ( 3 ..32 ) . contains ( & index) {
103
+ self . bits = bf_insert ( self . bits , index, 1 , hpm as usize ) ;
104
+ Ok ( ( ) )
105
+ } else {
106
+ Err ( Error :: IndexOutOfBounds {
107
+ index,
108
+ min : 3 ,
109
+ max : 31 ,
110
+ } )
111
+ }
68
112
}
69
113
}
70
114
@@ -85,16 +129,62 @@ set_clear_csr!(
85
129
/// Supervisor instret Enable
86
130
, set_ir, clear_ir, 1 << 2 ) ;
87
131
132
+ /// Enables the "hpm\[X\]" counter.
133
+ ///
134
+ /// Updates the `mcounteren` register.
135
+ ///
136
+ /// **WARNING**: panics on:
137
+ ///
138
+ /// - non-`riscv` targets
139
+ /// - `index` out-of-bounds
88
140
#[ inline]
89
141
pub unsafe fn set_hpm ( index : usize ) {
90
- assert ! ( ( 3 ..32 ) . contains( & index) ) ;
91
- _set ( 1 << index) ;
142
+ try_set_hpm ( index) . unwrap ( ) ;
143
+ }
144
+
145
+ /// Attempts to enable the "hpm\[X\]" counter.
146
+ ///
147
+ /// Updates the `mcounteren` register.
148
+ #[ inline]
149
+ pub unsafe fn try_set_hpm ( index : usize ) -> Result < ( ) > {
150
+ if ( 3 ..32 ) . contains ( & index) {
151
+ _try_set ( 1 << index)
152
+ } else {
153
+ Err ( Error :: IndexOutOfBounds {
154
+ index,
155
+ min : 3 ,
156
+ max : 31 ,
157
+ } )
158
+ }
92
159
}
93
160
161
+ /// Disables the "hpm\[X\]" counter.
162
+ ///
163
+ /// Updates the `mcounteren` register.
164
+ ///
165
+ /// **WARNING**: panics on:
166
+ ///
167
+ /// - non-`riscv` targets
168
+ /// - `index` out-of-bounds
94
169
#[ inline]
95
170
pub unsafe fn clear_hpm ( index : usize ) {
96
- assert ! ( ( 3 ..32 ) . contains( & index) ) ;
97
- _clear ( 1 << index) ;
171
+ try_clear_hpm ( index) . unwrap ( ) ;
172
+ }
173
+
174
+ /// Attempts to disable the "hpm\[X\]" counter.
175
+ ///
176
+ /// Updates the `mcounteren` register.
177
+ #[ inline]
178
+ pub unsafe fn try_clear_hpm ( index : usize ) -> Result < ( ) > {
179
+ if ( 3 ..32 ) . contains ( & index) {
180
+ _try_clear ( 1 << index)
181
+ } else {
182
+ Err ( Error :: IndexOutOfBounds {
183
+ index,
184
+ min : 3 ,
185
+ max : 31 ,
186
+ } )
187
+ }
98
188
}
99
189
100
190
#[ cfg( test) ]
@@ -131,12 +221,34 @@ mod tests {
131
221
132
222
( 3 ..32 ) . for_each ( |i| {
133
223
assert ! ( !m. hpm( i) ) ;
224
+ assert_eq ! ( m. try_hpm( i) , Ok ( false ) ) ;
134
225
135
226
m. set_hpm ( i, true ) ;
136
227
assert ! ( m. hpm( i) ) ;
137
228
138
- m. set_hpm ( i, false ) ;
229
+ assert_eq ! ( m. try_set_hpm( i, false ) , Ok ( ( ) ) ) ;
230
+ assert_eq ! ( m. try_hpm( i) , Ok ( false ) ) ;
231
+
139
232
assert ! ( !m. hpm( i) ) ;
140
233
} ) ;
234
+
235
+ ( 0 ..3 ) . chain ( 32 ..64 ) . for_each ( |index| {
236
+ assert_eq ! (
237
+ m. try_hpm( index) ,
238
+ Err ( Error :: IndexOutOfBounds {
239
+ index,
240
+ min: 3 ,
241
+ max: 31
242
+ } )
243
+ ) ;
244
+ assert_eq ! (
245
+ m. try_set_hpm( index, false ) ,
246
+ Err ( Error :: IndexOutOfBounds {
247
+ index,
248
+ min: 3 ,
249
+ max: 31
250
+ } )
251
+ ) ;
252
+ } )
141
253
}
142
254
}
0 commit comments