Skip to content

Commit

Permalink
Merge pull request #217 from rmsyn/riscv/mcounteren-in-mem
Browse files Browse the repository at this point in the history
riscv: add `mcounteren` in-memory update functions
  • Loading branch information
romancardenas authored May 28, 2024
2 parents ee84d85 + 6304be4 commit 7291ac2
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 5 deletions.
1 change: 1 addition & 0 deletions riscv/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
the CSR
- Export `riscv::register::macros` module macros for external use
- Add `riscv::register::mcountinhibit` module for `mcountinhibit` CSR
- Add `Mcounteren` in-memory update functions

### Fixed

Expand Down
89 changes: 84 additions & 5 deletions riscv/src/register/mcounteren.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! mcounteren register

use crate::bits::{bf_extract, bf_insert};

/// mcounteren register
#[derive(Clone, Copy, Debug)]
pub struct Mcounteren {
Expand All @@ -10,31 +12,64 @@ impl Mcounteren {
/// Supervisor "cycle\[h\]" Enable
#[inline]
pub fn cy(&self) -> bool {
self.bits & (1 << 0) != 0
bf_extract(self.bits, 0, 1) != 0
}

/// Sets whether to enable the "cycle\[h\]" counter.
///
/// Only updates the in-memory value, does not modify the `mcounteren` register.
#[inline]
pub fn set_cy(&mut self, cy: bool) {
self.bits = bf_insert(self.bits, 0, 1, cy as usize);
}

/// Supervisor "time\[h\]" Enable
#[inline]
pub fn tm(&self) -> bool {
self.bits & (1 << 1) != 0
bf_extract(self.bits, 1, 1) != 0
}

/// Sets whether to enable "time\[h\]".
///
/// Only updates the in-memory value, does not modify the `mcounteren` register.
#[inline]
pub fn set_tm(&mut self, tm: bool) {
self.bits = bf_insert(self.bits, 1, 1, tm as usize);
}

/// Supervisor "instret\[h\]" Enable
#[inline]
pub fn ir(&self) -> bool {
self.bits & (1 << 2) != 0
bf_extract(self.bits, 2, 1) != 0
}

/// Sets whether to enable the "instret\[h\]" counter.
///
/// Only updates the in-memory value, does not modify the `mcounteren` register.
#[inline]
pub fn set_ir(&mut self, ir: bool) {
self.bits = bf_insert(self.bits, 2, 1, ir as usize);
}

/// Supervisor "hpm\[x\]" Enable (bits 3-31)
#[inline]
pub fn hpm(&self, index: usize) -> bool {
assert!((3..32).contains(&index));
self.bits & (1 << index) != 0
bf_extract(self.bits, index, 1) != 0
}

/// Sets whether to enable the "hpm\[X\]" counter.
///
/// Only updates the in-memory value, does not modify the `mcounteren` 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!(Mcounteren, 0x306);
write_csr!(0x306);
write_csr_as!(Mcounteren, 0x306);
set!(0x306);
clear!(0x306);

Expand All @@ -61,3 +96,47 @@ pub unsafe fn clear_hpm(index: usize) {
assert!((3..32).contains(&index));
_clear(1 << index);
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_mcounteren() {
let mut m = Mcounteren { bits: 0 };

assert!(!m.cy());

m.set_cy(true);
assert!(m.cy());

m.set_cy(false);
assert!(!m.cy());

assert!(!m.tm());

m.set_tm(true);
assert!(m.tm());

m.set_tm(false);
assert!(!m.tm());

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));
});
}
}

0 comments on commit 7291ac2

Please sign in to comment.