Skip to content

Commit fe2f55f

Browse files
Merge pull request #360 from KushalMeghani1644/mtopi
Add mtopi CSR
2 parents 9a8e95d + e4d57d2 commit fe2f55f

File tree

4 files changed

+104
-0
lines changed

4 files changed

+104
-0
lines changed

riscv/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
99

1010
### Added
1111

12+
- Add Mtopi
1213
- Added DCSR (Debug Control and Status Register) CSR support for the RISC-V
1314
- Add `miselect` CSR
1415
- Improved assembly macro handling in asm.rs

riscv/src/register.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ pub mod mepc;
8989
pub mod mip;
9090
pub mod mscratch;
9191
pub mod mtinst;
92+
pub mod mtopi;
9293
pub mod mtval;
9394
pub mod mtval2;
9495
pub mod mvien;

riscv/src/register/macros.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,3 +1070,15 @@ macro_rules! test_csr_field {
10701070
}
10711071
}};
10721072
}
1073+
1074+
#[cfg(test)]
1075+
#[macro_export]
1076+
macro_rules! test_ro_csr_field {
1077+
($reg:ident, $field:ident: [$start:expr, $end:expr], $expected:expr) => {{
1078+
let bits = $reg.bits();
1079+
let exp_val = $crate::bits::bf_extract(bits, $start, $end - $start + 1);
1080+
let val = $reg.$field();
1081+
assert_eq!(val, exp_val);
1082+
assert_eq!(val, $expected);
1083+
}};
1084+
}

riscv/src/register/mtopi.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
//! mtopi register — Machine Top Priority Interrupt (0x7C0)
2+
//!
3+
//! Provides information about the highest-priority pending interrupt when AIA (Advanced Interrupt Architecture) is supported.
4+
//! This CSR is part of the RISC-V Advanced Interrupt Architecture extension and allows software to quickly
5+
//! identify the most important pending interrupt without scanning through multiple interrupt pending registers.
6+
//!
7+
//! # Usage
8+
//!
9+
//! ```no_run
10+
//! use riscv::register::mtopi;
11+
//!
12+
//! // Read the machine top priority interrupt register
13+
//! let mtopi_val = mtopi::read();
14+
//!
15+
//! if mtopi_val.is_interrupt_pending() {
16+
//! let interrupt_id = mtopi_val.iid();
17+
//! let priority = mtopi_val.iprio();
18+
//! println!("Highest priority interrupt: ID={}, Priority={}", interrupt_id, priority);
19+
//! } else {
20+
//! println!("No interrupts pending");
21+
//! }
22+
//! ```
23+
24+
read_only_csr! {
25+
/// Machine Top Priority Interrupt Register
26+
Mtopi: 0x7C0,
27+
mask: 0x0FFF_00FF,
28+
}
29+
30+
read_only_csr_field! {
31+
Mtopi,
32+
/// Interrupt ID (bits 16..27)
33+
///
34+
/// Identifies the specific interrupt source. A value of 0 indicates no interrupt is pending.
35+
/// Non-zero values correspond to specific interrupt sources as defined by the interrupt controller.
36+
iid: [16:27],
37+
}
38+
39+
read_only_csr_field! {
40+
Mtopi,
41+
/// Interrupt Priority ID (bits 0..7)
42+
///
43+
/// Represents the priority level of the pending interrupt.
44+
/// Lower numerical values indicate higher priority interrupts.
45+
iprio: [0:7],
46+
}
47+
48+
impl Mtopi {
49+
/// Returns true if there is a valid interrupt pending
50+
///
51+
/// When this returns true, both `interrupt_id()` and `priority()` will return meaningful values.
52+
#[inline]
53+
pub fn is_interrupt_pending(&self) -> bool {
54+
self.iid() != 0
55+
}
56+
}
57+
58+
#[cfg(test)]
59+
mod tests {
60+
use super::*;
61+
62+
#[test]
63+
fn test_mtopi_fields() {
64+
let mtopi = Mtopi::from_bits(0);
65+
test_ro_csr_field!(mtopi, iid: [16, 27], 0x0);
66+
test_ro_csr_field!(mtopi, iprio: [0, 7], 0x0);
67+
68+
let mtopi = Mtopi::from_bits((0xB << 16) | 5);
69+
test_ro_csr_field!(mtopi, iid: [16, 27], 0xB);
70+
test_ro_csr_field!(mtopi, iprio: [0, 7], 0x5);
71+
72+
let mtopi = Mtopi::from_bits((0xFFF << 16) | 0xFF);
73+
test_ro_csr_field!(mtopi, iid: [16, 27], 0xFFF);
74+
test_ro_csr_field!(mtopi, iprio: [0, 7], 0xFF);
75+
76+
let mtopi = Mtopi::from_bits(1 << 16);
77+
test_ro_csr_field!(mtopi, iid: [16, 27], 0x1);
78+
test_ro_csr_field!(mtopi, iprio: [0, 7], 0x0);
79+
80+
let mtopi = Mtopi::from_bits(1);
81+
test_ro_csr_field!(mtopi, iid: [16, 27], 0x0);
82+
test_ro_csr_field!(mtopi, iprio: [0, 7], 0x1);
83+
}
84+
85+
#[test]
86+
fn test_mtopi_bitmask() {
87+
let mtopi = Mtopi::from_bits(usize::MAX);
88+
assert_eq!(mtopi.bits(), 0x0FFF_00FFusize);
89+
}
90+
}

0 commit comments

Comments
 (0)