Skip to content

Commit 2f85419

Browse files
Implement VSTOPI CSR for RISC-V
1 parent 680892b commit 2f85419

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

riscv/src/register.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ pub mod sepc;
6363
pub mod sip;
6464
pub mod sscratch;
6565
pub mod stval;
66+
pub mod vstopi;
6667

6768
// Supervisor Protection and Translation
6869
pub mod satp;

riscv/src/register/vstopi.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
//! vstopi register — Virtual Supervisor Top Priority Interrupt (0xEB0)
2+
3+
read_only_csr! {
4+
/// Virtual Supervisor Top Priority Interrupt Register
5+
Vstopi: 0xEB0,
6+
mask: 0x0FFF_00FF,
7+
}
8+
9+
read_only_csr_field! {
10+
Vstopi,
11+
/// Interrupt ID (bits 16..27)
12+
///
13+
/// Identifies the specific interrupt source. A value of 0 indicates no interrupt is pending.
14+
/// Non-zero values correspond to specific interrupt sources as defined by the interrupt controller.
15+
iid: [16:27],
16+
}
17+
18+
read_only_csr_field! {
19+
Vstopi,
20+
/// Interrupt Priority ID (bits 0..7)
21+
///
22+
/// Represents the priority level of the pending interrupt.
23+
/// Lower numerical values indicate higher priority interrupts.
24+
iprio: [0:7],
25+
}
26+
27+
impl Vstopi {
28+
/// Returns true if there is a valid interrupt pending
29+
///
30+
/// When this returns true, both `interrupt_id()` and `priority()` will return meaningful values.
31+
#[inline]
32+
pub fn is_interrupt_pending(&self) -> bool {
33+
self.iid() != 0
34+
}
35+
}
36+
37+
#[cfg(test)]
38+
mod tests {
39+
use super::*;
40+
41+
#[test]
42+
fn test_vstopi_fields() {
43+
let vstopi = Vstopi::from_bits(0);
44+
test_ro_csr_field!(vstopi, iid: [16, 27], 0x0);
45+
test_ro_csr_field!(vstopi, iprio: [0, 7], 0x0);
46+
47+
let vstopi = Vstopi::from_bits((0xB << 16) | 5);
48+
test_ro_csr_field!(vstopi, iid: [16, 27], 0xB);
49+
test_ro_csr_field!(vstopi, iprio: [0, 7], 0x5);
50+
51+
let vstopi = Vstopi::from_bits((0xFFF << 16) | 0xFF);
52+
test_ro_csr_field!(vstopi, iid: [16, 27], 0xFFF);
53+
test_ro_csr_field!(vstopi, iprio: [0, 7], 0xFF);
54+
55+
let vstopi = Vstopi::from_bits(1 << 16);
56+
test_ro_csr_field!(vstopi, iid: [16, 27], 0x1);
57+
test_ro_csr_field!(vstopi, iprio: [0, 7], 0x0);
58+
59+
let vstopi = Vstopi::from_bits(1);
60+
test_ro_csr_field!(vstopi, iid: [16, 27], 0x0);
61+
test_ro_csr_field!(vstopi, iprio: [0, 7], 0x1);
62+
}
63+
64+
#[test]
65+
fn test_vstopi_bitmask() {
66+
let vstopi = Vstopi::from_bits(usize::MAX);
67+
assert_eq!(vstopi.bits(), 0x0FFF_00FFusize);
68+
}
69+
}

0 commit comments

Comments
 (0)