Skip to content

Commit

Permalink
riscv: add fallible functions to mcountinhibit
Browse files Browse the repository at this point in the history
Adds fallible access functions for `Mcountinhibit` HPM fields.
  • Loading branch information
rmsyn committed Jun 28, 2024
1 parent a10eb70 commit b7b9267
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 2 deletions.
1 change: 1 addition & 0 deletions riscv/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Add `riscv::register::mcountinhibit` module for `mcountinhibit` CSR
- Add `Mcounteren` in-memory update functions
- Add `Mstatus` vector extension support
- Add fallible counterparts to all functions that `panic`

### Fixed

Expand Down
87 changes: 85 additions & 2 deletions riscv/src/register/mcountinhibit.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! `mcountinhibit` register

use crate::bits::{bf_extract, bf_insert};
use crate::result::{Error, Result};

/// `mcountinhibit` register
#[derive(Clone, Copy, Debug)]
Expand Down Expand Up @@ -44,6 +45,22 @@ impl Mcountinhibit {
bf_extract(self.bits, index, 1) != 0
}

/// Machine "hpm\[x\]" Disable (bits 3-31)
///
/// Attempts to read the "hpm\[x\]" value, and returns an error if the index is invalid.
#[inline]
pub fn try_hpm(&self, index: usize) -> Result<bool> {
if (3..32).contains(&index) {
Ok(bf_extract(self.bits, index, 1) != 0)
} else {
Err(Error::OutOfBounds {
index,
min: 3,
max: 31,
})
}
}

/// Sets whether to inhibit the "hpm\[X\]" counter.
///
/// Only updates the in-memory value, does not modify the `mcountinhibit` register.
Expand All @@ -52,6 +69,25 @@ impl Mcountinhibit {
assert!((3..32).contains(&index));
self.bits = bf_insert(self.bits, index, 1, hpm as usize);
}

/// Sets whether to inhibit the "hpm\[X\]" counter.
///
/// Only updates the in-memory value, does not modify the `mcountinhibit` register.
///
/// Attempts to update the "hpm\[x\]" value, and returns an error if the index is invalid.
#[inline]
pub fn try_set_hpm(&mut self, index: usize, hpm: bool) -> Result<()> {
if (3..32).contains(&index) {
self.bits = bf_insert(self.bits, index, 1, hpm as usize);
Ok(())
} else {
Err(Error::OutOfBounds {
index,
min: 3,
max: 31,
})
}
}
}

read_csr_as!(Mcountinhibit, 0x320);
Expand All @@ -73,12 +109,38 @@ pub unsafe fn set_hpm(index: usize) {
_set(1 << index);
}

#[inline]
pub unsafe fn try_set_hpm(index: usize) -> Result<()> {
if (3..32).contains(&index) {
_try_set(1 << index)
} else {
Err(Error::OutOfBounds {
index,
min: 3,
max: 31,
})
}
}

#[inline]
pub unsafe fn clear_hpm(index: usize) {
assert!((3..32).contains(&index));
_clear(1 << index);
}

#[inline]
pub unsafe fn try_clear_hpm(index: usize) -> Result<()> {
if (3..32).contains(&index) {
_try_clear(1 << index)
} else {
Err(Error::OutOfBounds {
index,
min: 3,
max: 31,
})
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand All @@ -105,12 +167,33 @@ mod tests {

(3..32).for_each(|i| {
assert!(!m.hpm(i));
assert_eq!(m.try_hpm(i), Ok(false));

m.set_hpm(i, true);
assert!(m.hpm(i));
assert_eq!(m.try_hpm(i), Ok(true));

m.set_hpm(i, false);
assert!(!m.hpm(i));
assert_eq!(m.try_set_hpm(i, false), Ok(()));
assert_eq!(m.try_hpm(i), Ok(false));
});

(0..2).chain(32..64).for_each(|index| {
assert_eq!(
m.try_hpm(index),
Err(Error::OutOfBounds {
index,
min: 3,
max: 31
})
);
assert_eq!(
m.try_set_hpm(index, false),
Err(Error::OutOfBounds {
index,
min: 3,
max: 31
})
);
});
}
}

0 comments on commit b7b9267

Please sign in to comment.