Skip to content

Commit 7291ac2

Browse files
Merge pull request #217 from rmsyn/riscv/mcounteren-in-mem
riscv: add `mcounteren` in-memory update functions
2 parents ee84d85 + 6304be4 commit 7291ac2

File tree

2 files changed

+85
-5
lines changed

2 files changed

+85
-5
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: 84 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//! mcounteren register
22
3+
use crate::bits::{bf_extract, bf_insert};
4+
35
/// mcounteren register
46
#[derive(Clone, Copy, Debug)]
57
pub struct Mcounteren {
@@ -10,31 +12,64 @@ impl Mcounteren {
1012
/// Supervisor "cycle\[h\]" Enable
1113
#[inline]
1214
pub fn cy(&self) -> bool {
13-
self.bits & (1 << 0) != 0
15+
bf_extract(self.bits, 0, 1) != 0
16+
}
17+
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);
1424
}
1525

1626
/// Supervisor "time\[h\]" Enable
1727
#[inline]
1828
pub fn tm(&self) -> bool {
19-
self.bits & (1 << 1) != 0
29+
bf_extract(self.bits, 1, 1) != 0
30+
}
31+
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);
2038
}
2139

2240
/// Supervisor "instret\[h\]" Enable
2341
#[inline]
2442
pub fn ir(&self) -> bool {
25-
self.bits & (1 << 2) != 0
43+
bf_extract(self.bits, 2, 1) != 0
44+
}
45+
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);
2652
}
2753

2854
/// Supervisor "hpm\[x\]" Enable (bits 3-31)
2955
#[inline]
3056
pub fn hpm(&self, index: usize) -> bool {
3157
assert!((3..32).contains(&index));
32-
self.bits & (1 << index) != 0
58+
bf_extract(self.bits, index, 1) != 0
59+
}
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);
3368
}
3469
}
3570

3671
read_csr_as!(Mcounteren, 0x306);
37-
write_csr!(0x306);
72+
write_csr_as!(Mcounteren, 0x306);
3873
set!(0x306);
3974
clear!(0x306);
4075

@@ -61,3 +96,47 @@ pub unsafe fn clear_hpm(index: usize) {
6196
assert!((3..32).contains(&index));
6297
_clear(1 << index);
6398
}
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)