11//! mcounteren register
22
33use crate :: bits:: { bf_extract, bf_insert} ;
4+ use crate :: result:: { Error , Result } ;
45
56/// mcounteren register
67#[ derive( Clone , Copy , Debug ) ]
@@ -52,19 +53,62 @@ impl Mcounteren {
5253 }
5354
5455 /// Supervisor "hpm\[x\]" Enable (bits 3-31)
56+ ///
57+ /// **WARNING**: panics on:
58+ ///
59+ /// - non-`riscv` targets
60+ /// - `index` out-of-bounds
5561 #[ inline]
5662 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+ }
5980 }
6081
6182 /// Sets whether to enable the "hpm\[X\]" counter.
6283 ///
6384 /// 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
6490 #[ inline]
6591 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+ }
68112 }
69113}
70114
@@ -85,16 +129,62 @@ set_clear_csr!(
85129/// Supervisor instret Enable
86130 , set_ir, clear_ir, 1 << 2 ) ;
87131
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
88140#[ inline]
89141pub 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+ }
92159}
93160
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
94169#[ inline]
95170pub 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+ }
98188}
99189
100190#[ cfg( test) ]
@@ -131,12 +221,34 @@ mod tests {
131221
132222 ( 3 ..32 ) . for_each ( |i| {
133223 assert ! ( !m. hpm( i) ) ;
224+ assert_eq ! ( m. try_hpm( i) , Ok ( false ) ) ;
134225
135226 m. set_hpm ( i, true ) ;
136227 assert ! ( m. hpm( i) ) ;
137228
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+
139232 assert ! ( !m. hpm( i) ) ;
140233 } ) ;
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+ } )
141253 }
142254}
0 commit comments