riscv/register/
mcounteren.rs

1//! mcounteren register
2
3use crate::result::{Error, Result};
4
5read_write_csr! {
6    /// `mcounteren` register
7    Mcounteren: 0x306,
8    mask: 0xffff_ffff,
9}
10
11read_write_csr_field! {
12    Mcounteren,
13    /// Supervisor "cycle\[h\]" Enable
14    cy: 0,
15}
16
17read_write_csr_field! {
18    Mcounteren,
19    /// Supervisor "time\[h\]" Enable
20    tm: 1,
21}
22
23read_write_csr_field! {
24    Mcounteren,
25    /// Supervisor "instret\[h\]" Enable
26    ir: 2,
27}
28
29read_write_csr_field! {
30    Mcounteren,
31    /// Supervisor "hpm\[x\]" Enable (bits 3-31)
32    hpm: 3..=31,
33}
34
35set!(0x306);
36clear!(0x306);
37
38set_clear_csr!(
39/// Supervisor cycle Enable
40    , set_cy, clear_cy, 1 << 0);
41
42set_clear_csr!(
43/// Supervisor time Enable
44    , set_tm, clear_tm, 1 << 1);
45
46set_clear_csr!(
47/// Supervisor instret Enable
48    , set_ir, clear_ir, 1 << 2);
49
50/// Enables the "hpm\[X\]" counter.
51///
52/// Updates the `mcounteren` register.
53///
54/// **WARNING**: panics on:
55///
56/// - non-`riscv` targets
57/// - `index` out-of-bounds
58#[inline]
59pub unsafe fn set_hpm(index: usize) {
60    try_set_hpm(index).unwrap();
61}
62
63/// Attempts to enable the "hpm\[X\]" counter.
64///
65/// Updates the `mcounteren` register.
66#[inline]
67pub unsafe fn try_set_hpm(index: usize) -> Result<()> {
68    if (3..32).contains(&index) {
69        _try_set(1 << index)
70    } else {
71        Err(Error::IndexOutOfBounds {
72            index,
73            min: 3,
74            max: 31,
75        })
76    }
77}
78
79/// Disables the "hpm\[X\]" counter.
80///
81/// Updates the `mcounteren` register.
82///
83/// **WARNING**: panics on:
84///
85/// - non-`riscv` targets
86/// - `index` out-of-bounds
87#[inline]
88pub unsafe fn clear_hpm(index: usize) {
89    try_clear_hpm(index).unwrap();
90}
91
92/// Attempts to disable the "hpm\[X\]" counter.
93///
94/// Updates the `mcounteren` register.
95#[inline]
96pub unsafe fn try_clear_hpm(index: usize) -> Result<()> {
97    if (3..32).contains(&index) {
98        _try_clear(1 << index)
99    } else {
100        Err(Error::IndexOutOfBounds {
101            index,
102            min: 3,
103            max: 31,
104        })
105    }
106}
107
108#[cfg(test)]
109mod tests {
110    use super::*;
111
112    #[test]
113    fn test_mcounteren() {
114        let mut m = Mcounteren { bits: 0 };
115
116        test_csr_field!(m, cy);
117        test_csr_field!(m, tm);
118        test_csr_field!(m, ir);
119
120        (3..32).for_each(|i| test_csr_field!(m, hpm, i));
121
122        (0..3).chain(32..64).for_each(|index| {
123            test_csr_field!(
124                m,
125                hpm,
126                index,
127                Error::IndexOutOfBounds {
128                    index,
129                    min: 3,
130                    max: 31
131                }
132            )
133        });
134    }
135}