From b1acbfd3fcce4c40ce1c298b266ec274e174754d Mon Sep 17 00:00:00 2001 From: rmsyn Date: Wed, 22 May 2024 00:56:58 +0000 Subject: [PATCH] riscv: add `mcountinhibit` module Adds the `riscv::register::mcountinhibit` module for the `mcountinhibit` CSR. --- riscv/CHANGELOG.md | 1 + riscv/src/register.rs | 1 + riscv/src/register/mcountinhibit.rs | 116 ++++++++++++++++++++++++++++ 3 files changed, 118 insertions(+) create mode 100644 riscv/src/register/mcountinhibit.rs diff --git a/riscv/CHANGELOG.md b/riscv/CHANGELOG.md index 22e0ddec..6f2b963a 100644 --- a/riscv/CHANGELOG.md +++ b/riscv/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Add `Mstatus::update_*` helpers to manipulate Mstatus values without touching the CSR - Export `riscv::register::macros` module macros for external use +- Add `riscv::register::mcountinhibit` module for `mcountinhibit` CSR ### Fixed diff --git a/riscv/src/register.rs b/riscv/src/register.rs index d38db22d..e99264b5 100644 --- a/riscv/src/register.rs +++ b/riscv/src/register.rs @@ -95,6 +95,7 @@ mod pmpaddrx; pub use self::pmpaddrx::*; // Machine Counter/Timers +pub mod mcountinhibit; pub mod mcycle; pub mod mcycleh; mod mhpmcounterx; diff --git a/riscv/src/register/mcountinhibit.rs b/riscv/src/register/mcountinhibit.rs new file mode 100644 index 00000000..fca8cce7 --- /dev/null +++ b/riscv/src/register/mcountinhibit.rs @@ -0,0 +1,116 @@ +//! `mcountinhibit` register + +use crate::bits::{bf_extract, bf_insert}; + +/// `mcountinhibit` register +#[derive(Clone, Copy, Debug)] +pub struct Mcountinhibit { + bits: usize, +} + +impl Mcountinhibit { + /// Machine "cycle\[h\]" Disable + #[inline] + pub fn cy(&self) -> bool { + bf_extract(self.bits, 0, 1) != 0 + } + + /// Sets whether to inhibit the "cycle\[h\]" counter. + /// + /// Only updates the in-memory value, does not modify the `mcountinhibit` register. + #[inline] + pub fn set_cy(&mut self, cy: bool) { + self.bits = bf_insert(self.bits, 0, 1, cy as usize); + } + + /// Machine "instret\[h\]" Disable + #[inline] + pub fn ir(&self) -> bool { + bf_extract(self.bits, 2, 1) != 0 + } + + /// Sets whether to inhibit the "instret\[h\]" counter. + /// + /// Only updates the in-memory value, does not modify the `mcountinhibit` register. + #[inline] + pub fn set_ir(&mut self, ir: bool) { + self.bits = bf_insert(self.bits, 2, 1, ir as usize); + } + + /// Machine "hpm\[x\]" Disable (bits 3-31) + #[inline] + pub fn hpm(&self, index: usize) -> bool { + assert!((3..32).contains(&index)); + bf_extract(self.bits, index, 1) != 0 + } + + /// Sets whether to inhibit the "hpm\[X\]" counter. + /// + /// Only updates the in-memory value, does not modify the `mcountinhibit` register. + #[inline] + pub fn set_hpm(&mut self, index: usize, hpm: bool) { + assert!((3..32).contains(&index)); + self.bits = bf_insert(self.bits, index, 1, hpm as usize); + } +} + +read_csr_as!(Mcountinhibit, 0x320); +write_csr_as!(Mcountinhibit, 0x320); +set!(0x320); +clear!(0x320); + +set_clear_csr!( +/// Machine cycle Disable + , set_cy, clear_cy, 1 << 0); + +set_clear_csr!( +/// Machine instret Disable + , set_ir, clear_ir, 1 << 2); + +#[inline] +pub unsafe fn set_hpm(index: usize) { + assert!((3..32).contains(&index)); + _set(1 << index); +} + +#[inline] +pub unsafe fn clear_hpm(index: usize) { + assert!((3..32).contains(&index)); + _clear(1 << index); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_mcountinhibit() { + let mut m = Mcountinhibit { bits: 0 }; + + assert!(!m.cy()); + + m.set_cy(true); + assert!(m.cy()); + + m.set_cy(false); + assert!(!m.cy()); + + assert!(!m.ir()); + + m.set_ir(true); + assert!(m.ir()); + + m.set_ir(false); + assert!(!m.ir()); + + (3..32).for_each(|i| { + assert!(!m.hpm(i)); + + m.set_hpm(i, true); + assert!(m.hpm(i)); + + m.set_hpm(i, false); + assert!(!m.hpm(i)); + }); + } +}