1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
//! mhint, machine hint register
//!
//! # Notes on Accure Exception Enable bit
//!
//! When this bit is set, the processor is in precise exception mode.
//! And when this bit is cleared, the processor is in non-precise exception mode.
//!
//! This bit is set to true on reset, and is supported on Xuantie E907 and E906 cores.
//!
//! ## Precise exception
//!
//! Because the return delay of the bus access error exception signal generated by
//! the load/store instruction accessing the bus is unpredictable,
//! the processor will block the pipeline when executing the load/store instruction,
//! and subsequent instructions will not be issued and executed.
//!
//! Until the exception signal returns to the processor and enters the exception service routine,
//! the `mepc` will save the PC of the load/store instruction that generated the bus access exception,
//! so as to realize the precise exception.
//!
//! ## Non-precise exception
//!
//! The processor will not block the pipeline when executing the load/store instruction.
//! If the subsequent instruction is not a load store instruction (in another word, structural contention)
//! and has no data correlation with the load/store instruction, it can continue to execute.
//!
//! When the bus access error exception signal is sent to the processor and the exception service routine is entered,
//! the `mepc` will save the PC of the instruction being executed in the EX stage of the pipeline,
//! not necessarily the PC of the load/store instruction where the memory access error exception occurred.
//!
//! ## PMP behavior
//!
//! It should be noted that even if this bit is cleared, the memory access error exception caused
//! by the PMP permission mismatch in the execution of the load/store instruction is accurate.
//! In addition, in the non-precise exception mode, the update value of the `mtval` register is accurate,
//! that is, the address that generates the memory access error exception is accurately saved.
//!
//! # Platform support
//!
//! This register is supported on Xuantie C910, C906, E907 and E906 cores.
use bit_field::BitField;
use core::arch::asm;

/// L1 D-cache write allocation strategy
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum AMR {
    /// Depends on WA page entry attibute
    DependsOnWA = 0,
    /// Don't write to L1 cache after 3 continuous cache line writes
    After3Lines = 1,
    /// Don't write to L1 cache after 64 continuous cache line writes
    After64Lines = 2,
    /// Don't write to L1 cache after 128 continuous cache line writes
    After128Lines = 3,
}

/// D-cache prefetch lines
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum PrefN {
    /// Prefetch 2 lines
    TwoLines = 0,
    /// Prefetch 4 lines
    FourLines = 1,
    /// Prefetch 8 lines
    EightLines = 2,
    /// Prefetch 16 lines
    SixteenLines = 3,
}

set_clear_csr! {
    /// D-cache prefetch enable
    , 0x7C5, set_dpld, clear_dpld, 1 << 2
}
set_clear_csr! {
    /// I-cache prefetch enable
    , 0x7C5, set_ipld, clear_ipld, 1 << 8
}
set_clear_csr! {
    /// Accure exception enable
    ///
    /// # Platform support
    ///
    /// This bit is supported on Xuantie E907 and E906 cores.
    , 0x7C5, set_aee, clear_aee, 1 << 20
}

/// Set D-cache write allocation strategy
#[inline]
pub unsafe fn set_amr(amr: AMR) {
    let mut value: usize;
    asm!("csrr {}, 0x7C5", out(reg) value);
    value.set_bits(3..=4, amr as usize);
    asm!("csrw 0x7C5, {}", in(reg) value);
}

/// Set D-cache prefetch lines configuration
#[inline]
pub unsafe fn set_prefn(prefn: PrefN) {
    let mut value: usize;
    asm!("csrr {}, 0x7C5", out(reg) value);
    value.set_bits(13..=14, prefn as usize);
    asm!("csrw 0x7C5, {}", in(reg) value);
}