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

- Added `mtopi` CSR support for the RISC-V Advanced Interrupt Architecture extension.
- Added DCSR (Debug Control and Status Register) CSR support for the RISC-V
- Add `miselect` CSR
- Improved assembly macro handling in asm.rs
Expand Down
1 change: 1 addition & 0 deletions riscv/src/register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ pub mod mepc;
pub mod mip;
pub mod mscratch;
pub mod mtinst;
pub mod mtopi;
pub mod mtval;
pub mod mtval2;

Expand Down
12 changes: 12 additions & 0 deletions riscv/src/register/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1041,6 +1041,18 @@ macro_rules! test_csr_field {
}
}};

// test a multi-bit bitfield for read-only CSR (must come before enum pattern)
($reg:ident, $field:ident: [$start:expr, $end:expr]) => {{
let bits = $reg.bits();
let exp_val = $crate::bits::bf_extract(bits, $start, $end - $start + 1);
assert_eq!($reg.$field(), exp_val);
}};

// test a multi-bit bitfield for read-only CSR with expected value
($reg:ident, $field:ident: [$start:expr, $end:expr], $expected:expr) => {{
assert_eq!($reg.$field(), $expected);
}};
Comment on lines +1044 to +1054
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// test a multi-bit bitfield for read-only CSR (must come before enum pattern)
($reg:ident, $field:ident: [$start:expr, $end:expr]) => {{
let bits = $reg.bits();
let exp_val = $crate::bits::bf_extract(bits, $start, $end - $start + 1);
assert_eq!($reg.$field(), exp_val);
}};
// test a multi-bit bitfield for read-only CSR with expected value
($reg:ident, $field:ident: [$start:expr, $end:expr], $expected:expr) => {{
assert_eq!($reg.$field(), $expected);
}};
// test a multi-bit bitfield for read-only CSR with expected value
($reg:ident, $field:ident: [$start:expr, $end:expr], $expected:expr) => {{
let bits = $reg.bits();
let exp_val = $crate::bits::bf_extract(bits, $start, $end - $start + 1);
assert_eq!($reg.$field(), exp_val);
assert_eq!($reg.$field(), $expected);
}};

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only one new test branch that does all the checks


// test an enum bit field
($reg:ident, $field:ident: $var:expr) => {{
$crate::paste! {
Expand Down
91 changes: 91 additions & 0 deletions riscv/src/register/mtopi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
//! mtopi register — Machine Top Priority Interrupt (0x7C0)
//!
//! Provides information about the highest-priority pending interrupt when AIA (Advanced Interrupt Architecture) is supported.
//! This CSR is part of the RISC-V Advanced Interrupt Architecture extension and allows software to quickly
//! identify the most important pending interrupt without scanning through multiple interrupt pending registers.
//!
//! # Usage
//!
//! ```no_run
//! use riscv::register::mtopi;
//!
//! // Read the machine top priority interrupt register
//! let mtopi_val = mtopi::read();
//!
//! if mtopi_val.has_interrupt() {
//! let interrupt_id = mtopi_val.iid();
//! let priority = mtopi_val.ipid();
//! println!("Highest priority interrupt: ID={}, Priority={}", interrupt_id, priority);
//! } else {
//! println!("No interrupts pending");
//! }
//! ```
read_only_csr! {
/// Machine Top Priority Interrupt Register
Mtopi: 0x7C0,
mask: 0x0FFF_00FF,
}

read_only_csr_field! {
Mtopi,
/// 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! {
Mtopi,
/// 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 Mtopi {
/// 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_mtopi_fields() {
let mtopi = Mtopi::from_bits(0);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

test_csr_field!(mtopi, iid: [16, 27], 0x0);
test_csr_field!(mtopi, iprio: [0, 7], 0x0);

let mtopi = Mtopi::from_bits((11 << 16) | 5);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For clarity, so the numbers coincide with the next checks

Suggested change
let mtopi = Mtopi::from_bits((11 << 16) | 5);
let mtopi = Mtopi::from_bits((11 << 0xB) | 0x5);

test_csr_field!(mtopi, iid: [16, 27], 0xB);
test_csr_field!(mtopi, iprio: [0, 7], 0x5);

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

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

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

#[test]
fn test_mtopi_bitmask() {
let mtopi = Mtopi::from_bits(usize::MAX);
assert_eq!(mtopi.bits(), usize::MAX);
}
}