Skip to content

Commit 6e2acd1

Browse files
committed
fixup: riscv: add mvienh review suggestions
1 parent 42346c2 commit 6e2acd1

File tree

1 file changed

+88
-9
lines changed

1 file changed

+88
-9
lines changed

riscv/src/register/mvienh.rs

Lines changed: 88 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,109 @@
11
//! mvienh register
22
3+
use crate::bits::{bf_extract, bf_insert};
4+
use riscv_pac::InterruptNumber;
5+
36
read_write_csr! {
47
/// `mvienh` register
58
Mvienh: 0x318,
69
mask: 0xffff_ffff,
710
}
811

9-
read_write_csr_field! {
10-
Mvienh,
11-
/// Represents the enable status of a virtual major interrupt.
12-
interrupt: 0..=31,
13-
}
14-
1512
set!(0x318);
1613
clear!(0x318);
1714

15+
impl Mvienh {
16+
/// Represents the value to shift interrupt numbers to their relative value.
17+
pub const INTERRUPT_SHIFT: usize = 32;
18+
/// Represents the minimum interrupt of the unlabelled virtual interrupt range.
19+
pub const MIN_INTERRUPT: usize = 32;
20+
/// Represents the maximum interrupt of the unlabelled virtual interrupt range.
21+
pub const MAX_INTERRUPT: usize = 63;
22+
23+
/// Gets whether the interrupt number is a valid virtual interrupt.
24+
#[inline]
25+
pub const fn is_valid_interrupt(int: usize) -> bool {
26+
matches!(int, Self::MIN_INTERRUPT..=Self::MAX_INTERRUPT)
27+
}
28+
29+
/// Shifts the high-order interrupt number bits down to their relative value.
30+
#[inline]
31+
pub const fn shift_interrupt(int: usize) -> usize {
32+
int.saturating_sub(Self::INTERRUPT_SHIFT)
33+
}
34+
35+
/// Check if a specific core interrupt source is enabled.
36+
#[inline]
37+
pub fn is_enabled<I: InterruptNumber>(&self, interrupt: I) -> bool {
38+
let n = interrupt.number();
39+
Self::is_valid_interrupt(n) && bf_extract(self.bits, Self::shift_interrupt(n), 1) != 0
40+
}
41+
42+
/// Enable a specific core interrupt source.
43+
#[inline]
44+
pub fn enable<I: InterruptNumber>(&mut self, interrupt: I) {
45+
let n = interrupt.number();
46+
47+
if Self::is_valid_interrupt(n) {
48+
self.bits = bf_insert(self.bits, Self::shift_interrupt(n), 1, 1);
49+
}
50+
}
51+
52+
/// Disable a specific core interrupt source.
53+
#[inline]
54+
pub fn disable<I: InterruptNumber>(&mut self, interrupt: I) {
55+
let n = interrupt.number();
56+
57+
if Self::is_valid_interrupt(n) {
58+
self.bits = bf_insert(self.bits, Self::shift_interrupt(n), 1, 0);
59+
}
60+
}
61+
}
62+
1863
#[cfg(test)]
1964
mod tests {
2065
use super::*;
66+
use riscv_pac::result::{Error, Result};
67+
68+
/// Represents a custom set of virtual interrupts.
69+
///
70+
/// NOTE: a real implementation may want to enumerate the valid virtual interrupt variants.
71+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
72+
pub struct VirtualInterrupt(usize);
73+
74+
/// SAFETY: `Interrupt` represents the standard RISC-V interrupts
75+
unsafe impl InterruptNumber for VirtualInterrupt {
76+
const MAX_INTERRUPT_NUMBER: usize = Mvienh::MAX_INTERRUPT;
77+
78+
#[inline]
79+
fn number(self) -> usize {
80+
self.0
81+
}
82+
83+
#[inline]
84+
fn from_number(value: usize) -> Result<Self> {
85+
if Mvienh::is_valid_interrupt(value) {
86+
Ok(Self(value))
87+
} else {
88+
Err(Error::InvalidVariant(value))
89+
}
90+
}
91+
}
2192

2293
#[test]
2394
fn test_mvienh() {
2495
let mut m = Mvienh::from_bits(0);
2596

26-
(0..32).for_each(|idx| {
27-
test_csr_field!(m, interrupt, idx);
28-
});
97+
(Mvienh::MIN_INTERRUPT..=Mvienh::MAX_INTERRUPT)
98+
.filter_map(|n| VirtualInterrupt::from_number(n).ok())
99+
.for_each(|int| {
100+
assert!(!m.is_enabled(int));
101+
102+
m.enable(int);
103+
assert!(m.is_enabled(int));
104+
105+
m.disable(int);
106+
assert!(!m.is_enabled(int));
107+
});
29108
}
30109
}

0 commit comments

Comments
 (0)