Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions riscv/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
109 changes: 65 additions & 44 deletions riscv/src/register/scounteren.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<bool> {
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);

Expand All @@ -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) {
Expand All @@ -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) {
Expand All @@ -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)
});
}
}
4 changes: 2 additions & 2 deletions riscv/src/register/tests/read_write_csr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,12 @@ pub fn _try_read_csr() -> Result<Mtest> {

#[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]
Expand Down
4 changes: 2 additions & 2 deletions riscv/src/register/tests/write_only_csr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down