diff --git a/riscv/CHANGELOG.md b/riscv/CHANGELOG.md index 4925c446..8b081d34 100644 --- a/riscv/CHANGELOG.md +++ b/riscv/CHANGELOG.md @@ -35,6 +35,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Use CSR helper macros to define `pmpcfgx` field types - Use CSR helper macros to define `scause` field types - Use CSR helper macros to define `sie` register +- Use CSR helper macros to define `scounteren` field types ## [v0.12.1] - 2024-10-20 diff --git a/riscv/src/register/scounteren.rs b/riscv/src/register/scounteren.rs index 8559428c..e500307a 100644 --- a/riscv/src/register/scounteren.rs +++ b/riscv/src/register/scounteren.rs @@ -2,57 +2,36 @@ use crate::result::{Error, Result}; -/// scounteren register -#[derive(Clone, Copy, Debug)] -pub struct Scounteren { - bits: usize, +read_write_csr! { + /// scounteren register + Scounteren: 0x106, + mask: 0xffff_ffff, } -impl Scounteren { +read_write_csr_field! { + Scounteren, /// User "cycle\[h\]" Enable - #[inline] - pub fn cy(&self) -> bool { - self.bits & (1 << 0) != 0 - } + cy: 0, +} +read_write_csr_field! { + Scounteren, /// User "time\[h\]" Enable - #[inline] - pub fn tm(&self) -> bool { - self.bits & (1 << 1) != 0 - } + tm: 1, +} +read_write_csr_field! { + Scounteren, /// User "instret\[h]\" Enable - #[inline] - pub fn ir(&self) -> bool { - self.bits & (1 << 2) != 0 - } - - /// User "hpm\[x\]" Enable (bits 3-31) - #[inline] - pub fn hpm(&self, index: usize) -> bool { - assert!((3..32).contains(&index)); - self.bits & (1 << index) != 0 - } + ir: 2, +} +read_write_csr_field! { + Scounteren, /// User "hpm\[x\]" Enable (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 { - if (3..32).contains(&index) { - Ok(self.bits & (1 << index) != 0) - } else { - Err(Error::IndexOutOfBounds { - index, - min: 3, - max: 31, - }) - } - } + hpm: 3..=31, } -read_csr_as!(Scounteren, 0x106); -write_csr!(0x106); set!(0x106); clear!(0x106); @@ -68,12 +47,17 @@ set_clear_csr!( /// User instret Enable , set_ir, clear_ir, 1 << 2); +/// Sets the "hpm\[x\]" enable (bits 3-31). +/// +/// # Note +/// +/// Panics if `index` is out-of-bounds. #[inline] pub unsafe fn set_hpm(index: usize) { - assert!((3..32).contains(&index)); - _set(1 << index); + try_set_hpm(index).unwrap(); } +/// Attempts to set the "hpm\[x\]" enable (bits 3-31). #[inline] pub unsafe fn try_set_hpm(index: usize) -> Result<()> { if (3..32).contains(&index) { @@ -87,12 +71,17 @@ pub unsafe fn try_set_hpm(index: usize) -> Result<()> { } } +/// Clears the "hpm\[x\]" enable (bits 3-31). +/// +/// # Note +/// +/// Panics if `index` is out-of-bounds. #[inline] pub unsafe fn clear_hpm(index: usize) { - assert!((3..32).contains(&index)); - _clear(1 << index); + try_clear_hpm(index).unwrap() } +/// Attempts to clear the "hpm\[x\]" enable (bits 3-31). #[inline] pub unsafe fn try_clear_hpm(index: usize) -> Result<()> { if (3..32).contains(&index) { @@ -105,3 +94,35 @@ pub unsafe fn try_clear_hpm(index: usize) -> Result<()> { }) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_scounteren() { + const HPM_MIN: usize = 3; + const HPM_MAX: usize = 31; + + let mut scounteren = Scounteren::from_bits(0); + + test_csr_field!(scounteren, cy); + test_csr_field!(scounteren, tm); + test_csr_field!(scounteren, ir); + + (HPM_MIN..=HPM_MAX).for_each(|index| { + test_csr_field!(scounteren, hpm, index); + }); + + (0..usize::BITS as usize) + .filter(|&i| !(HPM_MIN..=HPM_MAX).any(|idx| idx == i)) + .for_each(|index| { + let err = Error::IndexOutOfBounds { + index, + min: 3, + max: 31, + }; + test_csr_field!(scounteren, hpm, index, err) + }); + } +} diff --git a/riscv/src/register/tests/read_write_csr.rs b/riscv/src/register/tests/read_write_csr.rs index a831c8c5..607de3a2 100644 --- a/riscv/src/register/tests/read_write_csr.rs +++ b/riscv/src/register/tests/read_write_csr.rs @@ -55,12 +55,12 @@ pub fn _try_read_csr() -> Result { #[allow(unused)] pub fn _write_csr(csr: Mtest) { - write(csr); + unsafe { write(csr) }; } #[allow(unused)] pub fn _try_write_csr(csr: Mtest) { - try_write(csr); + unsafe { try_write(csr) }; } #[test] diff --git a/riscv/src/register/tests/write_only_csr.rs b/riscv/src/register/tests/write_only_csr.rs index 6f51be18..94d37b31 100644 --- a/riscv/src/register/tests/write_only_csr.rs +++ b/riscv/src/register/tests/write_only_csr.rs @@ -45,12 +45,12 @@ write_only_csr_field! { // we don't test the `write` function, we are only testing in-memory functions. #[allow(unused)] pub fn _write_csr(csr: Mtest) { - write(csr); + unsafe { write(csr) }; } #[allow(unused)] pub fn _try_write_csr(csr: Mtest) -> Result<()> { - try_write(csr) + unsafe { try_write(csr) } } #[test]