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 `mtopei` CSR
- Add `mstatus` and `sstatus` CSRs helpers for UBE, VS, UXL and SXL, and the corresponding tests
- Add `pmpaddr16` ~ `pmpaddr63` CSRs
- Add `siselect` CSR
Expand Down
1 change: 1 addition & 0 deletions riscv/src/register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ pub mod mepc;
pub mod mip;
pub mod mscratch;
pub mod mtinst;
pub mod mtopei;
pub mod mtopi;
pub mod mtval;
pub mod mtval2;
Expand Down
70 changes: 70 additions & 0 deletions riscv/src/register/mtopei.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
//! `mtopei` register — Machine Top External Interrupt (0x35C)
//!
//! This CSR is part of the RISC-V Advanced Interrupt Architecture (AIA). Its layout mirrors
//! `mtopi`, exposing the interrupt identity and priority of the top pending machine external
//! interrupt.

read_write_csr! {
/// Machine Top External Interrupt Register
Mtopei: 0x35C,
mask: 0x0FFF_00FF,
}

read_write_csr_field! {
Mtopei,
/// Interrupt ID (bits 16..27)
///
/// Identifies the specific interrupt source. A value of 0 indicates no interrupt is pending.
iid: [16:27],
}

read_write_csr_field! {
Mtopei,
/// 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 Mtopei {
/// Returns true if there is a valid interrupt pending.
#[inline]
pub fn is_interrupt_pending(&self) -> bool {
self.iid() != 0
}
}

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

#[test]
fn test_mtopei_fields() {
let mut mtopei = Mtopei::from_bits(0);
test_csr_field!(mtopei, iid: [16, 27], 0x0);
test_csr_field!(mtopei, iprio: [0, 7], 0x0);

let mut mtopei = Mtopei::from_bits((0xB << 16) | 5);
test_csr_field!(mtopei, iid: [16, 27], 0xB);
test_csr_field!(mtopei, iprio: [0, 7], 0x5);

let mut mtopei = Mtopei::from_bits((0xFFF << 16) | 0xFF);
test_csr_field!(mtopei, iid: [16, 27], 0xFFF);
test_csr_field!(mtopei, iprio: [0, 7], 0xFF);

let mut mtopei = Mtopei::from_bits(1 << 16);
test_csr_field!(mtopei, iid: [16, 27], 0x1);
test_csr_field!(mtopei, iprio: [0, 7], 0x0);

let mut mtopei = Mtopei::from_bits(1);
test_csr_field!(mtopei, iid: [16, 27], 0x0);
test_csr_field!(mtopei, iprio: [0, 7], 0x1);
}

#[test]
fn test_mtopei_bitmask() {
let mtopei = Mtopei::from_bits(usize::MAX);
assert_eq!(mtopei.bits(), 0x0FFF_00FFusize);
}
}
Loading