Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions riscv/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

### Added

- Add `vstopi` CSR
- Add `dcsratch0` and `dscratch1` CSRs
- Add new `read-write_csr_as_usize` macro for registers
- Add `dpc` CSR support for RISC-V
Expand Down
1 change: 1 addition & 0 deletions riscv/src/register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ pub mod sepc;
pub mod sip;
pub mod sscratch;
pub mod stval;
pub mod vstopi;

// Supervisor Protection and Translation
pub mod satp;
Expand Down
69 changes: 69 additions & 0 deletions riscv/src/register/vstopi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//! vstopi register — Virtual Supervisor Top Priority Interrupt (0xEB0)

read_only_csr! {
/// Virtual Supervisor Top Priority Interrupt Register
Vstopi: 0xEB0,
mask: 0x0FFF_00FF,
}

read_only_csr_field! {
Vstopi,
/// Interrupt ID (bits 16..27)
///
/// Identifies the specific interrupt source. A value of 0 indicates no interrupt is pending.
/// Non-zero values correspond to specific interrupt sources as defined by the interrupt controller.
iid: [16:27],
}

read_only_csr_field! {
Vstopi,
/// Interrupt Priority ID (bits 0..7)
///
/// Represents the priority level of the pending interrupt.
/// Lower numerical values indicate higher priority interrupts.
iprio: [0:7],
}

impl Vstopi {
/// Returns true if there is a valid interrupt pending
///
/// When this returns true, both `interrupt_id()` and `priority()` will return meaningful values.
#[inline]
pub fn is_interrupt_pending(&self) -> bool {
self.iid() != 0
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_vstopi_fields() {
let vstopi = Vstopi::from_bits(0);
test_ro_csr_field!(vstopi, iid: [16, 27], 0x0);
test_ro_csr_field!(vstopi, iprio: [0, 7], 0x0);

let vstopi = Vstopi::from_bits((0xB << 16) | 5);
test_ro_csr_field!(vstopi, iid: [16, 27], 0xB);
test_ro_csr_field!(vstopi, iprio: [0, 7], 0x5);

let vstopi = Vstopi::from_bits((0xFFF << 16) | 0xFF);
test_ro_csr_field!(vstopi, iid: [16, 27], 0xFFF);
test_ro_csr_field!(vstopi, iprio: [0, 7], 0xFF);

let vstopi = Vstopi::from_bits(1 << 16);
test_ro_csr_field!(vstopi, iid: [16, 27], 0x1);
test_ro_csr_field!(vstopi, iprio: [0, 7], 0x0);

let vstopi = Vstopi::from_bits(1);
test_ro_csr_field!(vstopi, iid: [16, 27], 0x0);
test_ro_csr_field!(vstopi, iprio: [0, 7], 0x1);
}

#[test]
fn test_vstopi_bitmask() {
let vstopi = Vstopi::from_bits(usize::MAX);
assert_eq!(vstopi.bits(), 0x0FFF_00FFusize);
}
}