33pub use crate :: interrupt:: Trap ;
44pub use riscv_pac:: { CoreInterruptNumber , ExceptionNumber , InterruptNumber } ; // re-export useful riscv-pac traits
55
6- /// scause register
7- # [ derive ( Clone , Copy ) ]
8- pub struct Scause {
9- bits : usize ,
6+ read_write_csr ! {
7+ /// scause register
8+ Scause : 0x142 ,
9+ mask : usize :: MAX ,
1010}
1111
12- impl Scause {
13- /// Returns the contents of the register as raw bits
14- #[ inline]
15- pub fn bits ( & self ) -> usize {
16- self . bits
17- }
12+ #[ cfg( target_arch = "riscv32" ) ]
13+ read_write_csr_field ! {
14+ Scause ,
15+ /// Returns the type of the trap:
16+ ///
17+ /// - `true`: an interrupt caused the trap
18+ /// - `false`: an exception caused the trap
19+ interrupt: 31 ,
20+ }
21+
22+ #[ cfg( not( target_arch = "riscv32" ) ) ]
23+ read_write_csr_field ! {
24+ Scause ,
25+ /// Returns the type of the trap:
26+ ///
27+ /// - `true`: an interrupt caused the trap
28+ /// - `false`: an exception caused the trap
29+ interrupt: 63 ,
30+ }
1831
32+ #[ cfg( target_arch = "riscv32" ) ]
33+ read_write_csr_field ! {
34+ Scause ,
1935 /// Returns the code field
20- #[ inline]
21- pub fn code ( & self ) -> usize {
22- self . bits & !( 1 << ( usize:: BITS as usize - 1 ) )
23- }
36+ code: [ 0 : 30 ] ,
37+ }
38+
39+ #[ cfg( not( target_arch = "riscv32" ) ) ]
40+ read_write_csr_field ! {
41+ Scause ,
42+ /// Returns the code field
43+ code: [ 0 : 62 ] ,
44+ }
2445
46+ impl Scause {
2547 /// Returns the trap cause represented by this register.
2648 ///
2749 /// # Note
@@ -40,25 +62,16 @@ impl Scause {
4062 /// Is trap cause an interrupt.
4163 #[ inline]
4264 pub fn is_interrupt ( & self ) -> bool {
43- self . bits & ( 1 << ( usize :: BITS as usize - 1 ) ) != 0
65+ self . interrupt ( )
4466 }
4567
4668 /// Is trap cause an exception.
4769 #[ inline]
4870 pub fn is_exception ( & self ) -> bool {
49- !self . is_interrupt ( )
71+ !self . interrupt ( )
5072 }
5173}
5274
53- read_csr_as ! ( Scause , 0x142 ) ;
54- write_csr ! ( 0x142 ) ;
55-
56- /// Writes the CSR
57- #[ inline]
58- pub unsafe fn write ( bits : usize ) {
59- _write ( bits)
60- }
61-
6275/// Set supervisor cause register to corresponding cause.
6376#[ inline]
6477pub unsafe fn set < I : CoreInterruptNumber , E : ExceptionNumber > ( cause : Trap < I , E > ) {
@@ -70,3 +83,58 @@ pub unsafe fn set<I: CoreInterruptNumber, E: ExceptionNumber>(cause: Trap<I, E>)
7083 } ;
7184 _write ( bits) ;
7285}
86+
87+ #[ cfg( test) ]
88+ mod tests {
89+ use super :: * ;
90+
91+ #[ test]
92+ fn test_scause ( ) {
93+ let new_code = 0 ;
94+ ( 1usize ..=usize:: BITS as usize )
95+ . map ( |r| ( ( 1u128 << r) - 1 ) as usize )
96+ . for_each ( |raw| {
97+ let exp_interrupt = ( raw >> ( usize:: BITS - 1 ) ) != 0 ;
98+ let exp_code = raw & ( ( 1usize << ( usize:: BITS - 1 ) ) - 1 ) ;
99+ let exp_cause = if exp_interrupt {
100+ Trap :: Interrupt ( exp_code)
101+ } else {
102+ Trap :: Exception ( exp_code)
103+ } ;
104+
105+ let mut scause = Scause :: from_bits ( raw) ;
106+
107+ assert_eq ! ( scause. interrupt( ) , exp_interrupt) ;
108+ assert_eq ! ( scause. is_interrupt( ) , exp_interrupt) ;
109+ assert_eq ! ( scause. is_exception( ) , !exp_interrupt) ;
110+
111+ assert_eq ! ( scause. code( ) , exp_code) ;
112+ assert_eq ! ( scause. cause( ) , exp_cause) ;
113+
114+ scause. set_interrupt ( !exp_interrupt) ;
115+
116+ assert_eq ! ( scause. is_interrupt( ) , !exp_interrupt) ;
117+ assert_eq ! ( scause. is_exception( ) , exp_interrupt) ;
118+
119+ scause. set_code ( new_code) ;
120+ let new_cause = if scause. interrupt ( ) {
121+ Trap :: Interrupt ( new_code)
122+ } else {
123+ Trap :: Exception ( new_code)
124+ } ;
125+
126+ assert_eq ! ( scause. code( ) , new_code) ;
127+ assert_eq ! ( scause. cause( ) , new_cause) ;
128+
129+ scause. set_code ( exp_code) ;
130+ let exp_cause = if scause. interrupt ( ) {
131+ Trap :: Interrupt ( exp_code)
132+ } else {
133+ Trap :: Exception ( exp_code)
134+ } ;
135+
136+ assert_eq ! ( scause. code( ) , exp_code) ;
137+ assert_eq ! ( scause. cause( ) , exp_cause) ;
138+ } ) ;
139+ }
140+ }
0 commit comments