Skip to content

Commit 29dd75d

Browse files
Merge pull request #234 from rmsyn/riscv/mcounteren-csr-macro
riscv: use CSR macros for mcounteren
2 parents b7e9117 + 783906a commit 29dd75d

File tree

3 files changed

+57
-144
lines changed

3 files changed

+57
-144
lines changed

riscv/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1818
- Use CSR helper macros to define `mcause` register
1919
- Use CSR helper macros to define `medeleg` register
2020
- Use CSR helper macros to define `mideleg` register
21+
- Use CSR helper macros to define `mcounteren` register
2122

2223
## [v0.12.1] - 2024-10-20
2324

riscv/src/register/macros.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,6 +1063,7 @@ macro_rules! write_only_csr_field {
10631063
#[cfg(test)]
10641064
#[macro_export]
10651065
macro_rules! test_csr_field {
1066+
// test a single bit field
10661067
($reg:ident, $field:ident) => {{
10671068
$crate::paste! {
10681069
assert!(!$reg.$field());
@@ -1074,4 +1075,28 @@ macro_rules! test_csr_field {
10741075
assert!(!$reg.$field());
10751076
}
10761077
}};
1078+
1079+
// test a range bit field (valid)
1080+
($reg:ident, $field:ident, $index:expr) => {{
1081+
$crate::paste! {
1082+
assert!(!$reg.$field($index));
1083+
assert_eq!($reg.[<try_ $field>]($index), Ok(false));
1084+
1085+
$reg.[<set_ $field>]($index, true);
1086+
assert!($reg.$field($index));
1087+
1088+
assert_eq!($reg.[<try_set_ $field>]($index, false), Ok(()));
1089+
assert_eq!($reg.[<try_ $field>]($index), Ok(false));
1090+
1091+
assert!(!$reg.$field($index));
1092+
}
1093+
}};
1094+
1095+
// test a range bit field (invalid)
1096+
($reg:ident, $field:ident, $index:expr, $err:expr) => {{
1097+
$crate::paste! {
1098+
assert_eq!($reg.[<try_ $field>]($index), Err($err));
1099+
assert_eq!($reg.[<try_set_ $field>]($index, false), Err($err));
1100+
}
1101+
}};
10771102
}

riscv/src/register/mcounteren.rs

Lines changed: 31 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -1,113 +1,37 @@
11
//! mcounteren register
22
3-
use crate::bits::{bf_extract, bf_insert};
43
use crate::result::{Error, Result};
54

6-
/// mcounteren register
7-
#[derive(Clone, Copy, Debug)]
8-
pub struct Mcounteren {
9-
bits: usize,
5+
read_write_csr! {
6+
/// `mcounteren` register
7+
Mcounteren: 0x306,
8+
mask: 0xffff_ffff,
109
}
1110

12-
impl Mcounteren {
11+
read_write_csr_field! {
12+
Mcounteren,
1313
/// Supervisor "cycle\[h\]" Enable
14-
#[inline]
15-
pub fn cy(&self) -> bool {
16-
bf_extract(self.bits, 0, 1) != 0
17-
}
18-
19-
/// Sets whether to enable the "cycle\[h\]" counter.
20-
///
21-
/// Only updates the in-memory value, does not modify the `mcounteren` register.
22-
#[inline]
23-
pub fn set_cy(&mut self, cy: bool) {
24-
self.bits = bf_insert(self.bits, 0, 1, cy as usize);
25-
}
14+
cy: 0,
15+
}
2616

17+
read_write_csr_field! {
18+
Mcounteren,
2719
/// Supervisor "time\[h\]" Enable
28-
#[inline]
29-
pub fn tm(&self) -> bool {
30-
bf_extract(self.bits, 1, 1) != 0
31-
}
32-
33-
/// Sets whether to enable "time\[h\]".
34-
///
35-
/// Only updates the in-memory value, does not modify the `mcounteren` register.
36-
#[inline]
37-
pub fn set_tm(&mut self, tm: bool) {
38-
self.bits = bf_insert(self.bits, 1, 1, tm as usize);
39-
}
20+
tm: 1,
21+
}
4022

23+
read_write_csr_field! {
24+
Mcounteren,
4125
/// Supervisor "instret\[h\]" Enable
42-
#[inline]
43-
pub fn ir(&self) -> bool {
44-
bf_extract(self.bits, 2, 1) != 0
45-
}
46-
47-
/// Sets whether to enable the "instret\[h\]" counter.
48-
///
49-
/// Only updates the in-memory value, does not modify the `mcounteren` register.
50-
#[inline]
51-
pub fn set_ir(&mut self, ir: bool) {
52-
self.bits = bf_insert(self.bits, 2, 1, ir as usize);
53-
}
26+
ir: 2,
27+
}
5428

29+
read_write_csr_field! {
30+
Mcounteren,
5531
/// Supervisor "hpm\[x\]" Enable (bits 3-31)
56-
///
57-
/// **WARNING**: panics on `index` out-of-bounds
58-
#[inline]
59-
pub fn hpm(&self, index: usize) -> bool {
60-
self.try_hpm(index).unwrap()
61-
}
62-
63-
/// Fallible Supervisor "hpm\[x\]" Enable (bits 3-31).
64-
///
65-
/// Attempts to read the "hpm\[x\]" value, and returns an error if the `index` is invalid.
66-
#[inline]
67-
pub fn try_hpm(&self, index: usize) -> Result<bool> {
68-
if (3..32).contains(&index) {
69-
Ok(bf_extract(self.bits, index, 1) != 0)
70-
} else {
71-
Err(Error::IndexOutOfBounds {
72-
index,
73-
min: 3,
74-
max: 31,
75-
})
76-
}
77-
}
78-
79-
/// Sets whether to enable the "hpm\[X\]" counter.
80-
///
81-
/// Only updates the in-memory value, does not modify the `mcounteren` register.
82-
///
83-
/// **WARNING**: panics on `index` out-of-bounds
84-
#[inline]
85-
pub fn set_hpm(&mut self, index: usize, hpm: bool) {
86-
self.try_set_hpm(index, hpm).unwrap()
87-
}
88-
89-
/// Sets whether to enable the "hpm\[X\]" counter.
90-
///
91-
/// Only updates the in-memory value, does not modify the `mcounteren` register.
92-
///
93-
/// Attempts to update the "hpm\[x\]" value, and returns an error if the `index` is invalid.
94-
#[inline]
95-
pub fn try_set_hpm(&mut self, index: usize, hpm: bool) -> Result<()> {
96-
if (3..32).contains(&index) {
97-
self.bits = bf_insert(self.bits, index, 1, hpm as usize);
98-
Ok(())
99-
} else {
100-
Err(Error::IndexOutOfBounds {
101-
index,
102-
min: 3,
103-
max: 31,
104-
})
105-
}
106-
}
32+
hpm: 3..=31,
10733
}
10834

109-
read_csr_as!(Mcounteren, 0x306);
110-
write_csr_as!(Mcounteren, 0x306);
11135
set!(0x306);
11236
clear!(0x306);
11337

@@ -189,60 +113,23 @@ mod tests {
189113
fn test_mcounteren() {
190114
let mut m = Mcounteren { bits: 0 };
191115

192-
assert!(!m.cy());
193-
194-
m.set_cy(true);
195-
assert!(m.cy());
196-
197-
m.set_cy(false);
198-
assert!(!m.cy());
199-
200-
assert!(!m.tm());
201-
202-
m.set_tm(true);
203-
assert!(m.tm());
204-
205-
m.set_tm(false);
206-
assert!(!m.tm());
207-
208-
assert!(!m.ir());
209-
210-
m.set_ir(true);
211-
assert!(m.ir());
212-
213-
m.set_ir(false);
214-
assert!(!m.ir());
215-
216-
(3..32).for_each(|i| {
217-
assert!(!m.hpm(i));
218-
assert_eq!(m.try_hpm(i), Ok(false));
116+
test_csr_field!(m, cy);
117+
test_csr_field!(m, tm);
118+
test_csr_field!(m, ir);
219119

220-
m.set_hpm(i, true);
221-
assert!(m.hpm(i));
222-
223-
assert_eq!(m.try_set_hpm(i, false), Ok(()));
224-
assert_eq!(m.try_hpm(i), Ok(false));
225-
226-
assert!(!m.hpm(i));
227-
});
120+
(3..32).for_each(|i| test_csr_field!(m, hpm, i));
228121

229122
(0..3).chain(32..64).for_each(|index| {
230-
assert_eq!(
231-
m.try_hpm(index),
232-
Err(Error::IndexOutOfBounds {
233-
index,
234-
min: 3,
235-
max: 31
236-
})
237-
);
238-
assert_eq!(
239-
m.try_set_hpm(index, false),
240-
Err(Error::IndexOutOfBounds {
123+
test_csr_field!(
124+
m,
125+
hpm,
126+
index,
127+
Error::IndexOutOfBounds {
241128
index,
242129
min: 3,
243130
max: 31
244-
})
245-
);
246-
})
131+
}
132+
)
133+
});
247134
}
248135
}

0 commit comments

Comments
 (0)