Skip to content

Commit 6304be4

Browse files
committed
riscv: add mcounteren in-memory update functions
Adds functions for updating the in-memory `Mcounteren` structure without touching the CSR. Allows manipulating all bitfields in-memory, and writing the entire value back to the CSR at once.
1 parent 92e1e83 commit 6304be4

File tree

2 files changed

+80
-2
lines changed

2 files changed

+80
-2
lines changed

riscv/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1717
the CSR
1818
- Export `riscv::register::macros` module macros for external use
1919
- Add `riscv::register::mcountinhibit` module for `mcountinhibit` CSR
20+
- Add `Mcounteren` in-memory update functions
2021

2122
### Fixed
2223

riscv/src/register/mcounteren.rs

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! mcounteren register
22
3-
use crate::bits::bf_extract;
3+
use crate::bits::{bf_extract, bf_insert};
44

55
/// mcounteren register
66
#[derive(Clone, Copy, Debug)]
@@ -15,28 +15,61 @@ impl Mcounteren {
1515
bf_extract(self.bits, 0, 1) != 0
1616
}
1717

18+
/// Sets whether to enable the "cycle\[h\]" counter.
19+
///
20+
/// Only updates the in-memory value, does not modify the `mcounteren` register.
21+
#[inline]
22+
pub fn set_cy(&mut self, cy: bool) {
23+
self.bits = bf_insert(self.bits, 0, 1, cy as usize);
24+
}
25+
1826
/// Supervisor "time\[h\]" Enable
1927
#[inline]
2028
pub fn tm(&self) -> bool {
2129
bf_extract(self.bits, 1, 1) != 0
2230
}
2331

32+
/// Sets whether to enable "time\[h\]".
33+
///
34+
/// Only updates the in-memory value, does not modify the `mcounteren` register.
35+
#[inline]
36+
pub fn set_tm(&mut self, tm: bool) {
37+
self.bits = bf_insert(self.bits, 1, 1, tm as usize);
38+
}
39+
2440
/// Supervisor "instret\[h\]" Enable
2541
#[inline]
2642
pub fn ir(&self) -> bool {
2743
bf_extract(self.bits, 2, 1) != 0
2844
}
2945

46+
/// Sets whether to enable the "instret\[h\]" counter.
47+
///
48+
/// Only updates the in-memory value, does not modify the `mcounteren` register.
49+
#[inline]
50+
pub fn set_ir(&mut self, ir: bool) {
51+
self.bits = bf_insert(self.bits, 2, 1, ir as usize);
52+
}
53+
3054
/// Supervisor "hpm\[x\]" Enable (bits 3-31)
3155
#[inline]
3256
pub fn hpm(&self, index: usize) -> bool {
3357
assert!((3..32).contains(&index));
3458
bf_extract(self.bits, index, 1) != 0
3559
}
60+
61+
/// Sets whether to enable the "hpm\[X\]" counter.
62+
///
63+
/// Only updates the in-memory value, does not modify the `mcounteren` register.
64+
#[inline]
65+
pub fn set_hpm(&mut self, index: usize, hpm: bool) {
66+
assert!((3..32).contains(&index));
67+
self.bits = bf_insert(self.bits, index, 1, hpm as usize);
68+
}
3669
}
3770

3871
read_csr_as!(Mcounteren, 0x306);
39-
write_csr!(0x306);
72+
write_csr_as!(Mcounteren, 0x306);
4073
set!(0x306);
4174
clear!(0x306);
4275

@@ -63,3 +96,47 @@ pub unsafe fn clear_hpm(index: usize) {
6396
assert!((3..32).contains(&index));
6497
_clear(1 << index);
6598
}
99+
100+
#[cfg(test)]
101+
mod tests {
102+
use super::*;
103+
104+
#[test]
105+
fn test_mcounteren() {
106+
let mut m = Mcounteren { bits: 0 };
107+
108+
assert!(!m.cy());
109+
110+
m.set_cy(true);
111+
assert!(m.cy());
112+
113+
m.set_cy(false);
114+
assert!(!m.cy());
115+
116+
assert!(!m.tm());
117+
118+
m.set_tm(true);
119+
assert!(m.tm());
120+
121+
m.set_tm(false);
122+
assert!(!m.tm());
123+
124+
assert!(!m.ir());
125+
126+
m.set_ir(true);
127+
assert!(m.ir());
128+
129+
m.set_ir(false);
130+
assert!(!m.ir());
131+
132+
(3..32).for_each(|i| {
133+
assert!(!m.hpm(i));
134+
135+
m.set_hpm(i, true);
136+
assert!(m.hpm(i));
137+
138+
m.set_hpm(i, false);
139+
assert!(!m.hpm(i));
140+
});
141+
}
142+
}

0 commit comments

Comments
 (0)