-
Notifications
You must be signed in to change notification settings - Fork 184
Add mtopi CSR #347
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Add mtopi CSR #347
Changes from 4 commits
b2f88f8
15f8a16
311f82b
3a5c598
71ae94a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
//! 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.interrupt_id(); | ||
//! let priority = mtopi_val.priority(); | ||
//! 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: usize::MAX, | ||
} | ||
|
||
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. | ||
/// Higher numerical values indicate higher priority interrupts. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you read the documentation... It feels like it is the other way around. Higher numbers indicate lower priority. Or at least that is my understanding... |
||
ipid: [0:7], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to the specification, this field is called |
||
} | ||
|
||
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 has_interrupt(&self) -> bool { | ||
self.iid() != 0 | ||
} | ||
|
||
/// Returns the interrupt priority, with higher values indicating higher priority | ||
/// | ||
/// This value is only meaningful when `has_interrupt()` returns true. | ||
#[inline] | ||
pub fn priority(&self) -> usize { | ||
self.ipid() | ||
} | ||
|
||
/// Returns the interrupt identifier | ||
/// | ||
/// A value of 0 indicates no interrupt is pending. Non-zero values identify | ||
/// specific interrupt sources as defined by the interrupt controller configuration. | ||
#[inline] | ||
pub fn interrupt_id(&self) -> usize { | ||
self.iid() | ||
} | ||
KushalMeghani1644 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
fn test_mtopi_fields() { | ||
// Test using helper macros as requested - follows mcounteren.rs pattern | ||
let mut mtopi = Mtopi::from_bits(0); | ||
|
||
// Test iid field [16:27] - using test helper macro | ||
test_csr_field!(mtopi, iid: [16, 27]); | ||
// Test ipid field [0:7] - using test helper macro | ||
test_csr_field!(mtopi, ipid: [0, 7]); | ||
|
||
// Test helper methods | ||
assert!(!mtopi.has_interrupt()); | ||
assert_eq!(mtopi.priority(), 0); | ||
assert_eq!(mtopi.interrupt_id(), 0); | ||
|
||
// Test with some interrupt pending (IID = 11, IPID = 5) | ||
mtopi = Mtopi::from_bits((11 << 16) | 5); | ||
test_csr_field!(mtopi, iid: [16, 27]); | ||
test_csr_field!(mtopi, ipid: [0, 7]); | ||
assert!(mtopi.has_interrupt()); | ||
assert_eq!(mtopi.priority(), 5); | ||
assert_eq!(mtopi.interrupt_id(), 11); | ||
|
||
// Test maximum values for each field | ||
mtopi = Mtopi::from_bits((0xFFF << 16) | 0xFF); | ||
test_csr_field!(mtopi, iid: [16, 27]); | ||
test_csr_field!(mtopi, ipid: [0, 7]); | ||
assert!(mtopi.has_interrupt()); | ||
|
||
// Test field boundaries | ||
mtopi = Mtopi::from_bits(1 << 16); | ||
test_csr_field!(mtopi, iid: [16, 27]); | ||
test_csr_field!(mtopi, ipid: [0, 7]); | ||
|
||
mtopi = Mtopi::from_bits(1); | ||
test_csr_field!(mtopi, iid: [16, 27]); | ||
test_csr_field!(mtopi, ipid: [0, 7]); | ||
} | ||
|
||
#[test] | ||
fn test_mtopi_bitmask() { | ||
let mtopi = Mtopi::from_bits(usize::MAX); | ||
assert_eq!(mtopi.bits(), usize::MAX); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This mask is not correct. According to the specification, only bits 0 to 27 are used.