11//! mvien register
22
3+ use crate :: bits:: { bf_extract, bf_insert} ;
4+ use riscv_pac:: InterruptNumber ;
5+
36#[ cfg( target_arch = "riscv32" ) ]
47const MASK : usize = 0xffff_e222 ;
58#[ cfg( not( target_arch = "riscv32" ) ) ]
@@ -13,53 +16,127 @@ read_write_csr! {
1316
1417read_write_csr_field ! {
1518 Mvien ,
16- /// Alias of `mip.SSIP `
17- ssip : 1 ,
19+ /// Alias of `mie.SSIE `
20+ ssoft : 1 ,
1821}
1922
2023read_write_csr_field ! {
2124 Mvien ,
22- /// Alias of `mip.STIP `
23- stip : 5 ,
25+ /// Alias of `mie.STIE `
26+ stimer : 5 ,
2427}
2528
2629read_write_csr_field ! {
2730 Mvien ,
28- /// Alias of `mip.SEIP `
29- seip : 9 ,
31+ /// Alias of `mie.SEIE `
32+ sext : 9 ,
3033}
3134
32- #[ cfg( target_arch = "riscv32" ) ]
33- read_write_csr_field ! {
34- Mvien ,
35- /// Represents the enable status of a virtual major interrupt.
36- interrupt: 13 ..=31 ,
37- }
35+ impl Mvien {
36+ /// Represents the minimum interrupt of the unlabelled virtual interrupt range.
37+ pub const MIN_INTERRUPT : usize = 13 ;
38+ /// Represents the maximum interrupt of the unlabelled virtual interrupt range.
39+ #[ cfg( target_arch = "riscv32" ) ]
40+ pub const MAX_INTERRUPT : usize = 31 ;
41+ /// Represents the maximum interrupt of the unlabelled virtual interrupt range.
42+ #[ cfg( not( target_arch = "riscv32" ) ) ]
43+ pub const MAX_INTERRUPT : usize = 63 ;
3844
39- #[ cfg( not( target_arch = "riscv32" ) ) ]
40- read_write_csr_field ! {
41- Mvien ,
42- /// Represents the enable status of a virtual major interrupt.
43- interrupt: 13 ..=63 ,
45+ /// Gets whether the interrupt number is a valid virtual interrupt.
46+ #[ inline]
47+ pub const fn is_valid_interrupt ( int : usize ) -> bool {
48+ matches ! ( int, 1 | 5 | 9 | Self :: MIN_INTERRUPT ..=Self :: MAX_INTERRUPT )
49+ }
50+
51+ /// Check if a specific core interrupt source is enabled.
52+ #[ inline]
53+ pub fn is_enabled < I : InterruptNumber > ( & self , interrupt : I ) -> bool {
54+ let n = interrupt. number ( ) ;
55+ Self :: is_valid_interrupt ( n) && bf_extract ( self . bits , n, 1 ) != 0
56+ }
57+
58+ /// Enable a specific core interrupt source.
59+ #[ inline]
60+ pub fn enable < I : InterruptNumber > ( & mut self , interrupt : I ) {
61+ let n = interrupt. number ( ) ;
62+
63+ if Self :: is_valid_interrupt ( n) {
64+ self . bits = bf_insert ( self . bits , n, 1 , 1 ) ;
65+ }
66+ }
67+
68+ /// Disable a specific core interrupt source.
69+ #[ inline]
70+ pub fn disable < I : InterruptNumber > ( & mut self , interrupt : I ) {
71+ let n = interrupt. number ( ) ;
72+
73+ if Self :: is_valid_interrupt ( n) {
74+ self . bits = bf_insert ( self . bits , n, 1 , 0 ) ;
75+ }
76+ }
4477}
4578
4679set ! ( 0x308 ) ;
4780clear ! ( 0x308 ) ;
4881
82+ set_clear_csr ! (
83+ /// Supervisor Software Interrupt Enable
84+ , set_ssoft, clear_ssoft, 1 << 1 ) ;
85+ set_clear_csr ! (
86+ /// Supervisor Timer Interrupt Enable
87+ , set_stimer, clear_stimer, 1 << 5 ) ;
88+ set_clear_csr ! (
89+ /// Supervisor External Interrupt Enable
90+ , set_sext, clear_sext, 1 << 9 ) ;
91+
4992#[ cfg( test) ]
5093mod tests {
5194 use super :: * ;
95+ use riscv_pac:: result:: { Error , Result } ;
96+
97+ /// Represents a custom set of virtual interrupts.
98+ ///
99+ /// NOTE: a real implementation may want to enumerate the valid virtual interrupt variants.
100+ #[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
101+ pub struct VirtualInterrupt ( usize ) ;
102+
103+ /// SAFETY: `Interrupt` represents the standard RISC-V interrupts
104+ unsafe impl InterruptNumber for VirtualInterrupt {
105+ const MAX_INTERRUPT_NUMBER : usize = Mvien :: MAX_INTERRUPT ;
106+
107+ #[ inline]
108+ fn number ( self ) -> usize {
109+ self . 0
110+ }
111+
112+ #[ inline]
113+ fn from_number ( value : usize ) -> Result < Self > {
114+ if Mvien :: is_valid_interrupt ( value) {
115+ Ok ( Self ( value) )
116+ } else {
117+ Err ( Error :: InvalidVariant ( value) )
118+ }
119+ }
120+ }
52121
53122 #[ test]
54123 fn test_mvien ( ) {
55124 let mut m = Mvien :: from_bits ( 0 ) ;
56125
57- test_csr_field ! ( m, ssip) ;
58- test_csr_field ! ( m, stip) ;
59- test_csr_field ! ( m, seip) ;
126+ test_csr_field ! ( m, ssoft) ;
127+ test_csr_field ! ( m, stimer) ;
128+ test_csr_field ! ( m, sext) ;
129+
130+ ( 0 ..=VirtualInterrupt :: MAX_INTERRUPT_NUMBER )
131+ . filter_map ( |n| VirtualInterrupt :: from_number ( n) . ok ( ) )
132+ . for_each ( |int| {
133+ assert ! ( !m. is_enabled( int) ) ;
134+
135+ m. enable ( int) ;
136+ assert ! ( m. is_enabled( int) ) ;
60137
61- ( 13 .. 64 ) . for_each ( |idx| {
62- test_csr_field ! ( m , interrupt , idx ) ;
63- } ) ;
138+ m . disable ( int ) ;
139+ assert ! ( !m . is_enabled ( int ) ) ;
140+ } ) ;
64141 }
65142}
0 commit comments