From e279538c49a65d622735a2b3aa7afe58658fc83c Mon Sep 17 00:00:00 2001 From: KushalMeghani1644 Date: Fri, 31 Oct 2025 16:57:44 +0530 Subject: [PATCH 1/6] Add mtopi CSR --- riscv/CHANGELOG.md | 1 + riscv/src/register.rs | 1 + riscv/src/register/macros.rs | 8 ++++ riscv/src/register/mtopi.rs | 91 ++++++++++++++++++++++++++++++++++++ 4 files changed, 101 insertions(+) create mode 100644 riscv/src/register/mtopi.rs diff --git a/riscv/CHANGELOG.md b/riscv/CHANGELOG.md index 07d20828..4a6528c3 100644 --- a/riscv/CHANGELOG.md +++ b/riscv/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added +- Add Mtopi - Added DCSR (Debug Control and Status Register) CSR support for the RISC-V - Add `miselect` CSR - Improved assembly macro handling in asm.rs diff --git a/riscv/src/register.rs b/riscv/src/register.rs index a20328bc..72903fc6 100644 --- a/riscv/src/register.rs +++ b/riscv/src/register.rs @@ -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; diff --git a/riscv/src/register/macros.rs b/riscv/src/register/macros.rs index b5c9ee8e..8e80d771 100644 --- a/riscv/src/register/macros.rs +++ b/riscv/src/register/macros.rs @@ -1070,3 +1070,11 @@ macro_rules! test_csr_field { } }}; } + +#[cfg(test)] +#[macro_export] +macro_rules! test_ro_csr_field { + ($reg:ident, $field:ident: [$start:expr, $end:expr], $expected:expr) => {{ + assert_eq!($reg.$field(), $expected); + }}; +} diff --git a/riscv/src/register/mtopi.rs b/riscv/src/register/mtopi.rs new file mode 100644 index 00000000..06c5b467 --- /dev/null +++ b/riscv/src/register/mtopi.rs @@ -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.is_interrupt_pending() { +//! let interrupt_id = mtopi_val.iid(); +//! let priority = mtopi_val.iprio(); +//! 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); + + test_ro_csr_field!(mtopi, iid: [16, 27], 0x0); + test_ro_csr_field!(mtopi, iprio: [0, 7], 0x0); + + let mtopi = Mtopi::from_bits((11 << 16) | 5); + test_ro_csr_field!(mtopi, iid: [16, 27], 0xB); + test_ro_csr_field!(mtopi, iprio: [0, 7], 0x5); + + let mtopi = Mtopi::from_bits((0xFFF << 16) | 0xFF); + test_ro_csr_field!(mtopi, iid: [16, 27], 0xFFF); + test_ro_csr_field!(mtopi, iprio: [0, 7], 0xFF); + + let mtopi = Mtopi::from_bits(1 << 16); + test_ro_csr_field!(mtopi, iid: [16, 27], 0x1); + test_ro_csr_field!(mtopi, iprio: [0, 7], 0x0); + + let mtopi = Mtopi::from_bits(1); + test_ro_csr_field!(mtopi, iid: [16, 27], 0x0); + test_ro_csr_field!(mtopi, iprio: [0, 7], 0x1); + } + + #[test] + fn test_mtopi_bitmask() { + let mtopi = Mtopi::from_bits(usize::MAX); + assert_eq!(mtopi.bits(), 0x0FFF_00FFusize); + } +} From 56fe4c8bdb83fd392783148dc95bc95fb8c0b1bd Mon Sep 17 00:00:00 2001 From: Kushal Meghani <168952248+KushalMeghani1644@users.noreply.github.com> Date: Mon, 3 Nov 2025 18:58:24 +0530 Subject: [PATCH 2/6] Update riscv/src/register/mtopi.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Román Cárdenas Rodríguez --- riscv/src/register/mtopi.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/riscv/src/register/mtopi.rs b/riscv/src/register/mtopi.rs index 06c5b467..31b192f6 100644 --- a/riscv/src/register/mtopi.rs +++ b/riscv/src/register/mtopi.rs @@ -66,7 +66,7 @@ mod tests { test_ro_csr_field!(mtopi, iid: [16, 27], 0x0); test_ro_csr_field!(mtopi, iprio: [0, 7], 0x0); - let mtopi = Mtopi::from_bits((11 << 16) | 5); + let mtopi = Mtopi::from_bits((0xB << 16) | 5); test_ro_csr_field!(mtopi, iid: [16, 27], 0xB); test_ro_csr_field!(mtopi, iprio: [0, 7], 0x5); From 7b691f191a26a8e834caa3c5965198153dddff30 Mon Sep 17 00:00:00 2001 From: KushalMeghani1644 Date: Tue, 4 Nov 2025 17:40:23 +0530 Subject: [PATCH 3/6] Update macros.rs --- riscv/src/register/macros.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/riscv/src/register/macros.rs b/riscv/src/register/macros.rs index 8e80d771..b37c777e 100644 --- a/riscv/src/register/macros.rs +++ b/riscv/src/register/macros.rs @@ -1075,6 +1075,14 @@ macro_rules! test_csr_field { #[macro_export] macro_rules! test_ro_csr_field { ($reg:ident, $field:ident: [$start:expr, $end:expr], $expected:expr) => {{ - assert_eq!($reg.$field(), $expected); + let bits = $reg.bits(); + let shift = $end - $start + 1; + let mask = (1usize << shift) - 1; + let exp_val = (bits >> $start) & mask; + let val = $reg.$field(); + assert_eq!(val & !mask, 0); + assert_eq!($expected & !mask, 0); + assert_eq!(val, exp_val); + assert_eq!(val, $expected); }}; } From f1a09066531547d95a1f32b6947b393c0616a465 Mon Sep 17 00:00:00 2001 From: Kushal Meghani <168952248+KushalMeghani1644@users.noreply.github.com> Date: Wed, 5 Nov 2025 13:25:29 +0530 Subject: [PATCH 4/6] Update riscv/src/register/macros.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Román Cárdenas Rodríguez --- riscv/src/register/macros.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/riscv/src/register/macros.rs b/riscv/src/register/macros.rs index b37c777e..51bb94d7 100644 --- a/riscv/src/register/macros.rs +++ b/riscv/src/register/macros.rs @@ -1076,9 +1076,7 @@ macro_rules! test_csr_field { macro_rules! test_ro_csr_field { ($reg:ident, $field:ident: [$start:expr, $end:expr], $expected:expr) => {{ let bits = $reg.bits(); - let shift = $end - $start + 1; - let mask = (1usize << shift) - 1; - let exp_val = (bits >> $start) & mask; + let exp_val = $crate::bits::bf_extract(bits, $start, $end - $start + 1); let val = $reg.$field(); assert_eq!(val & !mask, 0); assert_eq!($expected & !mask, 0); From 51b82ff70db7d3a5cdd76c438a2158a3eecdc2c1 Mon Sep 17 00:00:00 2001 From: Kushal Meghani <168952248+KushalMeghani1644@users.noreply.github.com> Date: Wed, 5 Nov 2025 13:25:42 +0530 Subject: [PATCH 5/6] Update riscv/src/register/macros.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Román Cárdenas Rodríguez --- riscv/src/register/macros.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/riscv/src/register/macros.rs b/riscv/src/register/macros.rs index 51bb94d7..255f0f4e 100644 --- a/riscv/src/register/macros.rs +++ b/riscv/src/register/macros.rs @@ -1078,8 +1078,6 @@ macro_rules! test_ro_csr_field { let bits = $reg.bits(); let exp_val = $crate::bits::bf_extract(bits, $start, $end - $start + 1); let val = $reg.$field(); - assert_eq!(val & !mask, 0); - assert_eq!($expected & !mask, 0); assert_eq!(val, exp_val); assert_eq!(val, $expected); }}; From e4d57d2552f19eb63d2d59b826070d5cb76d16d2 Mon Sep 17 00:00:00 2001 From: Kushal Meghani <168952248+KushalMeghani1644@users.noreply.github.com> Date: Wed, 5 Nov 2025 13:25:55 +0530 Subject: [PATCH 6/6] Update riscv/src/register/mtopi.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Román Cárdenas Rodríguez --- riscv/src/register/mtopi.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/riscv/src/register/mtopi.rs b/riscv/src/register/mtopi.rs index 31b192f6..859b17c2 100644 --- a/riscv/src/register/mtopi.rs +++ b/riscv/src/register/mtopi.rs @@ -62,7 +62,6 @@ mod tests { #[test] fn test_mtopi_fields() { let mtopi = Mtopi::from_bits(0); - test_ro_csr_field!(mtopi, iid: [16, 27], 0x0); test_ro_csr_field!(mtopi, iprio: [0, 7], 0x0);