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 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
//! Platform specific SiFive CSRs
/// Branch prediction mode register
///
/// This SiFive custom extension adds an M-mode CSR to control the current branch prediction mode, bpm at CSR 0x7C0.
///
/// Depending on platform, the Core Complex’s branch prediction system may include a Return Address Stack (RAS),
/// a Branch Target Buffer (BTB), and a Branch History Table (BHT).
///
/// While branch predictors are essential to achieve high performance in pipelined processors, they can also cause
/// undesirable timing variability for hard real-time systems. The bpm register provides a means to customize
/// the branch predictor behavior to trade average performance for a more predictable execution time
pub mod mbpm {
use bit_field::BitField;
/// Branch prediction mode register
#[derive(Clone, Copy, Debug)]
#[repr(transparent)]
pub struct Mbpm {
bits: usize,
}
impl Mbpm {
/// Branch-Direction Prediction. Determines the value returned by the BHT component of the branch prediction system.
///
/// A zero value indicates dynamic direction prediction, and a non-zero value indicates static-taken direction prediction.
///
/// The BTB is cleared on any write to bdp, and the RAS is unaffected by writes to bdp.
#[inline]
pub fn bdp(&self) -> bool {
self.bits.get_bit(0)
}
}
/// Reads the register
#[inline]
pub fn read() -> Mbpm {
let bits: usize;
unsafe { asm!("csrr {}, 0x7C0", out(reg) bits) };
Mbpm { bits }
}
/// Set mode to dynamic direction prediction.
#[inline]
pub unsafe fn clear_bdp() {
asm!("csrrci 0x7C0, 0")
}
/// Set mode to static-taken direction prediction.
#[inline]
pub unsafe fn set_bdp() {
asm!("csrrsi 0x7C0, 0")
}
}
#[doc(hidden)] // hide by now, API has not been decided yet
/// Feature disable register
///
/// The SiFive custom M-mode Feature Disable CSR is provided to enable or disable certain
/// microarchitectural features.
///
/// A feature is fully enabled when the associated bit is zero. If a particular core does not support
/// the disabling of a feature, the corresponding bit is hardwired to zero.
///
/// On reset, all implemented bits are set to 1, disabling all features. The bootloader is responsible
/// for turning on all required features and can simply write zero to turn on the maximal set of features.
/// SiFive’s Freedom Metal bootloader handles turning on these features; when using a custom bootloader,
/// clearing the Feature Disable CSR must be implemented.
///
/// Note that arbitrary toggling of the Feature Disable CSR bits is neither recommended nor supported;
/// they are only intended to be set from 1 to 0. A particular Feature Disable CSR bit is only to be
/// used in a very limited number of situations, as detailed in the Example Usage entry in tables
/// on documentation of each core.
pub mod mfeature {
use crate::feature::Mask;
/// Clear corresponding bits in feature register
#[inline]
pub unsafe fn clear_features(flags: Mask) {
asm!("csrrc 0x7C1, {}", in(reg) flags.bits())
}
}
/// Rnmi scratch register
///
/// The mnscratch CSR holds a 64-bit read-write register, which enables the NMI trap handler
/// to save and restore the context that was interrupted.
pub mod mnscratch {
/// Reads the `mnscratch` register
#[inline]
pub fn read() -> usize {
let ans: usize;
unsafe { asm!("csrr {}, 0x351", out(reg) ans) };
ans
}
/// Writes the `mnscratch` register
#[inline]
pub unsafe fn write(data: usize) {
asm!("csrw 0x351, {}", in(reg) data)
}
}
/// Rnmi exception program counter register
///
/// The mnepc CSR is a 64-bit read-write register, which, on entry to the NMI trap handler,
/// holds the PC of the instruction that took the interrupt. The lowest bit of mnepc is
/// hardwired to zero.
pub mod mnepc {
/// Reads the `mnepc` register
#[inline]
pub fn read() -> usize {
let ans: usize;
unsafe { asm!("csrr {}, 0x351", out(reg) ans) };
ans
}
}
/// Rnmi cause register
///
/// The mncause CSR holds the reason for the NMI, with bit 63 set to 1, and the NMI cause
/// encoded in the least-significant bits, or zero if NMI causes are not supported.
///
/// The lower bits of mncause, defined as the exception_code, are as follows:
///
/// | mncause | NMI Cause | Function |
/// |:--------|:----------|:---------|
/// | 1 | *Reserved* | *Reserved* |
/// | 2 | RNMI input pin | External `rnmi_N` input |
/// | 3 | Bus error | RNMI caused by BEU |
pub mod mncause {
/// NMI causes
#[repr(usize)]
pub enum Nmi {
RnmiInput = 2,
BusError = 3,
}
/// Check if NMI cause is supported
#[inline]
pub fn is_supported() -> bool {
let ans: usize;
unsafe { asm!("csrr {}, 0x352", out(reg) ans) };
ans != 0
}
/// Reads the NMI cause, or None if not supported
#[inline]
pub fn exception_code() -> Option<Nmi> {
let ans: usize;
unsafe { asm!("csrr {}, 0x352", out(reg) ans) };
match ans {
2 => Some(Nmi::RnmiInput),
3 => Some(Nmi::BusError),
_ => None,
}
}
}
/// Rnmi status register
///
/// The mnstatus CSR holds a two-bit field, which, on entry to the trap handler,
/// holds the privilege mode of the interrupted context encoded in the same manner
/// as mstatus.mpp.
pub mod mnstatus {}