Merge pull request #3 from Disasm/deduplicate

Remove all the modules present in the riscv crate, update docs
This commit is contained in:
Sean Cross 2020-06-14 22:33:16 +08:00 committed by GitHub
commit ba269ff348
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
62 changed files with 53 additions and 2458 deletions

View File

@ -8,9 +8,5 @@ description = "Low level access to the VexRiscv processor"
keywords = ["riscv", "register", "peripheral", "vexriscv"]
license = "ISC"
[dependencies]
bare-metal = ">=0.2.0,<0.2.5"
bit_field = "0.9.0"
[features]
inline-asm = []

View File

@ -1,7 +1,38 @@
# `veriscv`
[![crates.io](https://img.shields.io/crates/d/vexriscv.svg)](https://crates.io/crates/vexriscv)
[![crates.io](https://img.shields.io/crates/v/vexriscv.svg)](https://crates.io/crates/vexriscv)
[![Build Status](https://travis-ci.org/xobs/vexriscv-rust.svg?branch=master)](https://travis-ci.org/xobs/vexriscv-rust)
# `vexriscv`
> Low level access to parts of the VexRiscv RISC-V processor
THIS PROJECT IS NOW OBSOLETE
This project complements [riscv](https://github.com/rust-embedded/riscv),
which is developed and maintained by the [RISC-V team][team].
You can access vexriscv-specific csrs in the `riscv` crate, under `riscv::registers::vexriscv::*`.
## [Documentation](https://docs.rs/crate/vexriscv)
## License
Copyright 2020 Sean "xobs" Cross
Copyright 2019 [RISC-V team][team]
Permission to use, copy, modify, and/or distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright notice
and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
## Code of Conduct
Contribution to this crate is organized under the terms of the [Rust Code of
Conduct][CoC], the maintainer of this crate, the [RISC-V team][team], promises
to intervene to uphold that code of conduct.
[CoC]: CODE_OF_CONDUCT.md
[team]: https://github.com/rust-embedded/wg#the-riscv-team

280
asm.S
View File

@ -40,285 +40,11 @@ __clear_ ## name: \
#define RW32(offset, name)
#define RO32(offset, name)
#endif
// ----------------------- //
.section .text.__ebreak
.global __ebreak
__ebreak:
ebreak
ret
.section .text.__wfi
.global __wfi
__wfi:
wfi
ret
.section .text.__sfence_vma_all
.global __sfence_vma_all
__sfence_vma_all:
sfence.vma
ret
.section .text.__sfence_vma
.global __sfence_vma
__sfence_vma:
sfence.vma a0, a1
ret
// User Trap Setup
RW(0x000, ustatus) // User status register
RW(0x004, uie) // User interrupt-enable register
RW(0x005, utvec) // User trap handler base address
// User Trap Handling
RW(0x040, uscratch) // Scratch register for user trap handlers
RW(0x041, uepc) // User exception program counter
RW(0x042, ucause) // User trap cause
RW(0x043, utval) // User bad address or instruction
RW(0x044, uip) // User interrupt pending
// User Floating-Point CSRs
RW(0x001, fflags) // Floating-Point Accrued Exceptions
RW(0x002, frm) // Floating-Point Dynamic Rounding Mode
RW(0x003, fcsr) // Floating-Point Control and Status Register (frm + fflags)
// User Counter/Timers
RO( 0xC00, cycle) // Cycle counter for RDCYCLE instruction
RO( 0xC01, time) // Timer for RDTIME instruction
RO( 0xC02, instret) // Instructions-retired counter for RDINSTRET instruction
RO( 0xC03, hpmcounter3) // Performance-monitoring counter
RO( 0xC04, hpmcounter4) // Performance-monitoring counter
RO( 0xC05, hpmcounter5) // Performance-monitoring counter
RO( 0xC06, hpmcounter6) // Performance-monitoring counter
RO( 0xC07, hpmcounter7) // Performance-monitoring counter
RO( 0xC08, hpmcounter8) // Performance-monitoring counter
RO( 0xC09, hpmcounter9) // Performance-monitoring counter
RO( 0xC0A, hpmcounter10) // Performance-monitoring counter
RO( 0xC0B, hpmcounter11) // Performance-monitoring counter
RO( 0xC0C, hpmcounter12) // Performance-monitoring counter
RO( 0xC0D, hpmcounter13) // Performance-monitoring counter
RO( 0xC0E, hpmcounter14) // Performance-monitoring counter
RO( 0xC0F, hpmcounter15) // Performance-monitoring counter
RO( 0xC10, hpmcounter16) // Performance-monitoring counter
RO( 0xC11, hpmcounter17) // Performance-monitoring counter
RO( 0xC12, hpmcounter18) // Performance-monitoring counter
RO( 0xC13, hpmcounter19) // Performance-monitoring counter
RO( 0xC14, hpmcounter20) // Performance-monitoring counter
RO( 0xC15, hpmcounter21) // Performance-monitoring counter
RO( 0xC16, hpmcounter22) // Performance-monitoring counter
RO( 0xC17, hpmcounter23) // Performance-monitoring counter
RO( 0xC18, hpmcounter24) // Performance-monitoring counter
RO( 0xC19, hpmcounter25) // Performance-monitoring counter
RO( 0xC1A, hpmcounter26) // Performance-monitoring counter
RO( 0xC1B, hpmcounter27) // Performance-monitoring counter
RO( 0xC1C, hpmcounter28) // Performance-monitoring counter
RO( 0xC1D, hpmcounter29) // Performance-monitoring counter
RO( 0xC1E, hpmcounter30) // Performance-monitoring counter
RO( 0xC1F, hpmcounter31) // Performance-monitoring counter
RO32(0xC80, cycleh) // Upper 32 bits of cycle, RV32I only
RO32(0xC81, timeh) // Upper 32 bits of time, RV32I only
RO32(0xC82, instreth) // Upper 32 bits of instret, RV32I only
RO32(0xC83, hpmcounter3h) // Upper 32 bits of hpmcounter3, RV32I only
RO32(0xC84, hpmcounter4h)
RO32(0xC85, hpmcounter5h)
RO32(0xC86, hpmcounter6h)
RO32(0xC87, hpmcounter7h)
RO32(0xC88, hpmcounter8h)
RO32(0xC89, hpmcounter9h)
RO32(0xC8A, hpmcounter10h)
RO32(0xC8B, hpmcounter11h)
RO32(0xC8C, hpmcounter12h)
RO32(0xC8D, hpmcounter13h)
RO32(0xC8E, hpmcounter14h)
RO32(0xC8F, hpmcounter15h)
RO32(0xC90, hpmcounter16h)
RO32(0xC91, hpmcounter17h)
RO32(0xC92, hpmcounter18h)
RO32(0xC93, hpmcounter19h)
RO32(0xC94, hpmcounter20h)
RO32(0xC95, hpmcounter21h)
RO32(0xC96, hpmcounter22h)
RO32(0xC97, hpmcounter23h)
RO32(0xC98, hpmcounter24h)
RO32(0xC99, hpmcounter25h)
RO32(0xC9A, hpmcounter26h)
RO32(0xC9B, hpmcounter27h)
RO32(0xC9C, hpmcounter28h)
RO32(0xC9D, hpmcounter29h)
RO32(0xC9E, hpmcounter30h)
RO32(0xC9F, hpmcounter31h)
// Supervisor Trap Setup
RW(0x100, sstatus) // Supervisor status register
RW(0x102, sedeleg) // Supervisor exception delegation register
RW(0x103, sideleg) // Supervisor interrupt delegation register
RW(0x104, sie) // Supervisor interrupt-enable register
RW(0x105, stvec) // Supervisor trap handler base address
RW(0x106, scounteren) // Supervisor counter enable
// Supervisor Trap Handling
RW(0x140, sscratch) // Scratch register for supervisor trap handlers
RW(0x141, sepc) // Supervisor exception program counter
RW(0x142, scause) // Supervisor trap cause
RW(0x143, stval) // Supervisor bad address or instruction
RW(0x144, sip) // Supervisor interrupt pending
// Supervisor Protection and Translation
RW(0x180, satp) // Supervisor address translation and protection
// Machine Information Registers
RO(0xF11, mvendorid) // Vendor ID
RO(0xF12, marchid) // Architecture ID
RO(0xF13, mimpid) // Implementation ID
RO(0xF14, mhartid) // Hardware thread ID
// Machine Trap Setup
RW(0x300, mstatus) // Machine status register
RW(0x301, misa) // ISA and extensions
RW(0x302, medeleg) // Machine exception delegation register
RW(0x303, mideleg) // Machine interrupt delegation register
RW(0x304, mie) // Machine interrupt-enable register
RW(0x305, mtvec) // Machine trap handler base address
RW(0x306, mcounteren) // Machine counter enable
// Machine Trap Handling
RW(0x340, mscratch) // Scratch register for machine trap handlers
RW(0x341, mepc) // Machine exception program counter
RW(0x342, mcause) // Machine trap cause
RW(0x343, mtval) // Machine bad address or instruction
RW(0x344, mip) // Machine interrupt pending
// Machine Protection and Translation
RW( 0x3A0, pmpcfg0) // Physical memory protection configuration
RW32(0x3A1, pmpcfg1) // Physical memory protection configuration, RV32 only
RW( 0x3A2, pmpcfg2) // Physical memory protection configuration
RW32(0x3A3, pmpcfg3) // Physical memory protection configuration, RV32 only
RW( 0x3B0, pmpaddr0) // Physical memory protection address register
RW( 0x3B1, pmpaddr1) // Physical memory protection address register
RW( 0x3B2, pmpaddr2) // Physical memory protection address register
RW( 0x3B3, pmpaddr3) // Physical memory protection address register
RW( 0x3B4, pmpaddr4) // Physical memory protection address register
RW( 0x3B5, pmpaddr5) // Physical memory protection address register
RW( 0x3B6, pmpaddr6) // Physical memory protection address register
RW( 0x3B7, pmpaddr7) // Physical memory protection address register
RW( 0x3B8, pmpaddr8) // Physical memory protection address register
RW( 0x3B9, pmpaddr9) // Physical memory protection address register
RW( 0x3BA, pmpaddr10) // Physical memory protection address register
RW( 0x3BB, pmpaddr11) // Physical memory protection address register
RW( 0x3BC, pmpaddr12) // Physical memory protection address register
RW( 0x3BD, pmpaddr13) // Physical memory protection address register
RW( 0x3BE, pmpaddr14) // Physical memory protection address register
RW( 0x3BF, pmpaddr15) // Physical memory protection address register
// Machine Counter/Timers
RO( 0xB00, mcycle) // Machine cycle counter
RO( 0xB02, minstret) // Machine instructions-retired counter
RO( 0xB03, mhpmcounter3) // Machine performance-monitoring counter
RO( 0xB04, mhpmcounter4) // Machine performance-monitoring counter
RO( 0xB05, mhpmcounter5) // Machine performance-monitoring counter
RO( 0xB06, mhpmcounter6) // Machine performance-monitoring counter
RO( 0xB07, mhpmcounter7) // Machine performance-monitoring counter
RO( 0xB08, mhpmcounter8) // Machine performance-monitoring counter
RO( 0xB09, mhpmcounter9) // Machine performance-monitoring counter
RO( 0xB0A, mhpmcounter10) // Machine performance-monitoring counter
RO( 0xB0B, mhpmcounter11) // Machine performance-monitoring counter
RO( 0xB0C, mhpmcounter12) // Machine performance-monitoring counter
RO( 0xB0D, mhpmcounter13) // Machine performance-monitoring counter
RO( 0xB0E, mhpmcounter14) // Machine performance-monitoring counter
RO( 0xB0F, mhpmcounter15) // Machine performance-monitoring counter
RO( 0xB10, mhpmcounter16) // Machine performance-monitoring counter
RO( 0xB11, mhpmcounter17) // Machine performance-monitoring counter
RO( 0xB12, mhpmcounter18) // Machine performance-monitoring counter
RO( 0xB13, mhpmcounter19) // Machine performance-monitoring counter
RO( 0xB14, mhpmcounter20) // Machine performance-monitoring counter
RO( 0xB15, mhpmcounter21) // Machine performance-monitoring counter
RO( 0xB16, mhpmcounter22) // Machine performance-monitoring counter
RO( 0xB17, mhpmcounter23) // Machine performance-monitoring counter
RO( 0xB18, mhpmcounter24) // Machine performance-monitoring counter
RO( 0xB19, mhpmcounter25) // Machine performance-monitoring counter
RO( 0xB1A, mhpmcounter26) // Machine performance-monitoring counter
RO( 0xB1B, mhpmcounter27) // Machine performance-monitoring counter
RO( 0xB1C, mhpmcounter28) // Machine performance-monitoring counter
RO( 0xB1D, mhpmcounter29) // Machine performance-monitoring counter
RO( 0xB1E, mhpmcounter30) // Machine performance-monitoring counter
RO( 0xB1F, mhpmcounter31) // Machine performance-monitoring counter
RO32(0xB80, mcycleh) // Upper 32 bits of mcycle, RV32I only
RO32(0xB82, minstreth) // Upper 32 bits of minstret, RV32I only
RO32(0xB83, mhpmcounter3h) // Upper 32 bits of mhpmcounter3, RV32I only
RO32(0xB84, mhpmcounter4h)
RO32(0xB85, mhpmcounter5h)
RO32(0xB86, mhpmcounter6h)
RO32(0xB87, mhpmcounter7h)
RO32(0xB88, mhpmcounter8h)
RO32(0xB89, mhpmcounter9h)
RO32(0xB8A, mhpmcounter10h)
RO32(0xB8B, mhpmcounter11h)
RO32(0xB8C, mhpmcounter12h)
RO32(0xB8D, mhpmcounter13h)
RO32(0xB8E, mhpmcounter14h)
RO32(0xB8F, mhpmcounter15h)
RO32(0xB90, mhpmcounter16h)
RO32(0xB91, mhpmcounter17h)
RO32(0xB92, mhpmcounter18h)
RO32(0xB93, mhpmcounter19h)
RO32(0xB94, mhpmcounter20h)
RO32(0xB95, mhpmcounter21h)
RO32(0xB96, mhpmcounter22h)
RO32(0xB97, mhpmcounter23h)
RO32(0xB98, mhpmcounter24h)
RO32(0xB99, mhpmcounter25h)
RO32(0xB9A, mhpmcounter26h)
RO32(0xB9B, mhpmcounter27h)
RO32(0xB9C, mhpmcounter28h)
RO32(0xB9D, mhpmcounter29h)
RO32(0xB9E, mhpmcounter30h)
RO32(0xB9F, mhpmcounter31h)
RW(0x323, mhpmevent3) // Machine performance-monitoring event selector
RW(0x324, mhpmevent4) // Machine performance-monitoring event selector
RW(0x325, mhpmevent5) // Machine performance-monitoring event selector
RW(0x326, mhpmevent6) // Machine performance-monitoring event selector
RW(0x327, mhpmevent7) // Machine performance-monitoring event selector
RW(0x328, mhpmevent8) // Machine performance-monitoring event selector
RW(0x329, mhpmevent9) // Machine performance-monitoring event selector
RW(0x32A, mhpmevent10) // Machine performance-monitoring event selector
RW(0x32B, mhpmevent11) // Machine performance-monitoring event selector
RW(0x32C, mhpmevent12) // Machine performance-monitoring event selector
RW(0x32D, mhpmevent13) // Machine performance-monitoring event selector
RW(0x32E, mhpmevent14) // Machine performance-monitoring event selector
RW(0x32F, mhpmevent15) // Machine performance-monitoring event selector
RW(0x330, mhpmevent16) // Machine performance-monitoring event selector
RW(0x331, mhpmevent17) // Machine performance-monitoring event selector
RW(0x332, mhpmevent18) // Machine performance-monitoring event selector
RW(0x333, mhpmevent19) // Machine performance-monitoring event selector
RW(0x334, mhpmevent20) // Machine performance-monitoring event selector
RW(0x335, mhpmevent21) // Machine performance-monitoring event selector
RW(0x336, mhpmevent22) // Machine performance-monitoring event selector
RW(0x337, mhpmevent23) // Machine performance-monitoring event selector
RW(0x338, mhpmevent24) // Machine performance-monitoring event selector
RW(0x339, mhpmevent25) // Machine performance-monitoring event selector
RW(0x33A, mhpmevent26) // Machine performance-monitoring event selector
RW(0x33B, mhpmevent27) // Machine performance-monitoring event selector
RW(0x33C, mhpmevent28) // Machine performance-monitoring event selector
RW(0x33D, mhpmevent29) // Machine performance-monitoring event selector
RW(0x33E, mhpmevent30) // Machine performance-monitoring event selector
RW(0x33F, mhpmevent31) // Machine performance-monitoring event selector
// Debug/Trace Registers (shared with Debug Mode)
RW(0x7A0, tselect) // Debug/Trace trigger register select
RW(0x7A1, tdata1) // First Debug/Trace trigger data register
RW(0x7A2, tdata2) // Second Debug/Trace trigger data register
RW(0x7A3, tdata3) // Third Debug/Trace trigger data register
// Debug Mode Registers
RW(0x7B0, dcsr) // Debug control and status register
RW(0x7B1, dpc) // Debug PC
RW(0x7B2, dscratch) // Debug scratch register
// VexRiscv custom registers
RW(0xBC0, vmim) // Machine IRQ Mask
RW(0xFC0, vmip) // Machine IRQ Pending
RO(0xFC0, vmip) // Machine IRQ Pending
RW(0x9C0, vsim) // Supervisor IRQ Mask
RW(0xDC0, vsip) // Supervisor IRQ Pending
RW(0xCC0, vdci) // DCache Info
RO(0xDC0, vsip) // Supervisor IRQ Pending
RO(0xCC0, vdci) // DCache Info

View File

@ -5,14 +5,14 @@ Remove-Item -Force bin/*.a
$crate = "vexriscv"
riscv64-unknown-elf-gcc -c -mabi=ilp32 -march=rv32imac asm.S -o bin/$crate.o
riscv64-unknown-elf-gcc -ggdb3 -fdebug-prefix-map=$pwd=/vexriscv -c -mabi=ilp32 -march=rv32imac asm.S -o bin/$crate.o
riscv64-unknown-elf-ar crs bin/riscv32imac-unknown-none-elf.a bin/$crate.o
riscv64-unknown-elf-ar crs bin/riscv32imc-unknown-none-elf.a bin/$crate.o
riscv64-unknown-elf-gcc -c -mabi=ilp32 -march=rv32i asm.S -DSKIP_MULTICORE -o bin/$crate.o
riscv64-unknown-elf-gcc -ggdb3 -fdebug-prefix-map=$pwd=/vexriscv -c -mabi=ilp32 -march=rv32i asm.S -DSKIP_MULTICORE -o bin/$crate.o
riscv64-unknown-elf-ar crs bin/riscv32i-unknown-none-elf.a bin/$crate.o
riscv64-unknown-elf-gcc -c -mabi=lp64 -march=rv64imac asm.S -o bin/$crate.o
riscv64-unknown-elf-gcc -ggdb3 -fdebug-prefix-map=$pwd=/vexriscv -c -mabi=lp64 -march=rv64imac asm.S -o bin/$crate.o
riscv64-unknown-elf-ar crs bin/riscv64imac-unknown-none-elf.a bin/$crate.o
riscv64-unknown-elf-ar crs bin/riscv64gc-unknown-none-elf.a bin/$crate.o

View File

@ -7,14 +7,14 @@ crate=vexriscv
# remove existing blobs because otherwise this will append object files to the old blobs
rm -f bin/*.a
riscv64-unknown-elf-gcc -c -mabi=ilp32 -march=rv32imac asm.S -o bin/$crate.o
riscv64-unknown-elf-gcc -ggdb3 -fdebug-prefix-map=$(pwd)=/vexriscv -c -mabi=ilp32 -march=rv32imac asm.S -o bin/$crate.o
ar crs bin/riscv32imac-unknown-none-elf.a bin/$crate.o
ar crs bin/riscv32imc-unknown-none-elf.a bin/$crate.o
riscv64-unknown-elf-gcc -c -mabi=ilp32 -march=rv32i asm.S -DSKIP_MULTICORE -o bin/$crate.o
riscv64-unknown-elf-gcc -ggdb3 -fdebug-prefix-map=$(pwd)=/vexriscv -c -mabi=ilp32 -march=rv32i asm.S -DSKIP_MULTICORE -o bin/$crate.o
ar crs bin/riscv32i-unknown-none-elf.a bin/$crate.o
riscv64-unknown-elf-gcc -c -mabi=lp64 -march=rv64imac asm.S -o bin/$crate.o
riscv64-unknown-elf-gcc -ggdb3 -fdebug-prefix-map=$(pwd)=/vexriscv -c -mabi=lp64 -march=rv64imac asm.S -o bin/$crate.o
ar crs bin/riscv64imac-unknown-none-elf.a bin/$crate.o
ar crs bin/riscv64gc-unknown-none-elf.a bin/$crate.o

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,77 +0,0 @@
//! Assembly instructions
macro_rules! instruction {
($(#[$attr:meta])*, $fnname:ident, $asm:expr, $asm_fn:ident) => (
$(#[$attr])*
#[inline]
pub unsafe fn $fnname() {
match () {
#[cfg(all(riscv, feature = "inline-asm"))]
() => asm!($asm :::: "volatile"),
#[cfg(all(riscv, not(feature = "inline-asm")))]
() => {
extern "C" {
fn $asm_fn();
}
$asm_fn();
}
#[cfg(not(riscv))]
() => unimplemented!(),
}
}
)
}
instruction!(
/// `EBREAK` instruction wrapper
///
/// Generates a breakpoint exception.
, ebreak, "ebreak", __ebreak);
instruction!(
/// `WFI` instruction wrapper
///
/// Provides a hint to the implementation that the current hart can be stalled until an interrupt might need servicing.
/// The WFI instruction is just a hint, and a legal implementation is to implement WFI as a NOP.
, wfi, "wfi", __wfi);
instruction!(
/// `SFENCE.VMA` instruction wrapper (all address spaces and page table levels)
///
/// Synchronizes updates to in-memory memory-management data structures with current execution.
/// Instruction execution causes implicit reads and writes to these data structures; however, these implicit references
/// are ordinarily not ordered with respect to loads and stores in the instruction stream.
/// Executing an `SFENCE.VMA` instruction guarantees that any stores in the instruction stream prior to the
/// `SFENCE.VMA` are ordered before all implicit references subsequent to the `SFENCE.VMA`.
, sfence_vma_all, "sfence.vma", __sfence_vma_all);
/// `SFENCE.VMA` instruction wrapper
///
/// Synchronizes updates to in-memory memory-management data structures with current execution.
/// Instruction execution causes implicit reads and writes to these data structures; however, these implicit references
/// are ordinarily not ordered with respect to loads and stores in the instruction stream.
/// Executing an `SFENCE.VMA` instruction guarantees that any stores in the instruction stream prior to the
/// `SFENCE.VMA` are ordered before all implicit references subsequent to the `SFENCE.VMA`.
#[inline]
#[allow(unused_variables)]
pub unsafe fn sfence_vma(asid: usize, addr: usize) {
match () {
#[cfg(all(riscv, feature = "inline-asm"))]
() => asm!("sfence.vma $0, $1" :: "r"(asid), "r"(addr) :: "volatile"),
#[cfg(all(riscv, not(feature = "inline-asm")))]
() => {
extern "C" {
fn __sfence_vma(asid: usize, addr: usize);
}
__sfence_vma(asid, addr);
}
#[cfg(not(riscv))]
() => unimplemented!(),
}
}

View File

@ -1,54 +0,0 @@
//! Interrupts
// NOTE: Adapted from cortex-m/src/interrupt.rs
pub use bare_metal::{CriticalSection, Mutex, Nr};
use register::mstatus;
/// Disables all interrupts
#[inline]
pub unsafe fn disable() {
match () {
#[cfg(riscv)]
() => mstatus::clear_mie(),
#[cfg(not(riscv))]
() => unimplemented!(),
}
}
/// Enables all the interrupts
///
/// # Safety
///
/// - Do not call this function inside an `interrupt::free` critical section
#[inline]
pub unsafe fn enable() {
match () {
#[cfg(riscv)]
() => mstatus::set_mie(),
#[cfg(not(riscv))]
() => unimplemented!(),
}
}
/// Execute closure `f` in an interrupt-free context.
///
/// This as also known as a "critical section".
pub fn free<F, R>(f: F) -> R
where
F: FnOnce(&CriticalSection) -> R,
{
let mstatus = mstatus::read();
// disable interrupts
unsafe { disable(); }
let r = f(unsafe { &CriticalSection::new() });
// If the interrupts were active before our `disable` call, then re-enable
// them. Otherwise, keep them disabled
if mstatus.mie() {
unsafe { enable(); }
}
r
}

View File

@ -1,27 +1,6 @@
//! Low level access to RISC-V processors
//!
//! # Minimum Supported Rust Version (MSRV)
//!
//! This crate is guaranteed to compile on stable Rust 1.30 and up. It *might*
//! compile with older versions but that may change in any new patch release.
//! Note that `riscv64imac-unknown-none-elf` and `riscv64gc-unknown-none-elf` targets
//! are not supported on stable yet.
//!
//! # Features
//!
//! This crate provides:
//!
//! - Access to core registers like `mstatus` or `mcause`.
//! - Interrupt manipulation mechanisms.
//! - Wrappers around assembly instructions like `WFI`.
//! Low level access to VexRiscv RISC-V cores
#![no_std]
#![deny(warnings)]
#![cfg_attr(feature = "inline-asm", feature(asm))]
extern crate bare_metal;
extern crate bit_field;
pub mod asm;
pub mod interrupt;
pub mod register;

View File

@ -1,132 +0,0 @@
//! Floating-point control and status register
use bit_field::BitField;
/// Floating-point control and status register
#[derive(Clone, Copy, Debug)]
pub struct FCSR {
bits: u32,
}
/// Accrued Exception Flags
#[derive(Clone, Copy, Debug)]
pub struct Flags(u32);
/// Accrued Exception Flag
#[derive(Clone, Copy, Debug)]
pub enum Flag {
/// Inexact
NX = 0b00001,
/// Underflow
UF = 0b00010,
/// Overflow
OF = 0b00100,
/// Divide by Zero
DZ = 0b01000,
/// Invalid Operation
NV = 0b10000,
}
impl Flags {
/// Inexact
#[inline]
pub fn nx(&self) -> bool {
self.0.get_bit(0)
}
/// Underflow
#[inline]
pub fn uf(&self) -> bool {
self.0.get_bit(1)
}
/// Overflow
#[inline]
pub fn of(&self) -> bool {
self.0.get_bit(2)
}
/// Divide by Zero
#[inline]
pub fn dz(&self) -> bool {
self.0.get_bit(3)
}
/// Invalid Operation
#[inline]
pub fn nv(&self) -> bool {
self.0.get_bit(4)
}
}
/// Rounding Mode
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum RoundingMode {
RoundToNearestEven = 0b000,
RoundTowardsZero = 0b001,
RoundDown = 0b010,
RoundUp = 0b011,
RoundToNearestMaxMagnitude = 0b100,
Invalid = 0b111,
}
impl FCSR {
/// Returns the contents of the register as raw bits
pub fn bits(&self) -> u32 {
self.bits
}
/// Accrued Exception Flags
#[inline]
pub fn fflags(&self) -> Flags {
Flags(self.bits.get_bits(0..5))
}
/// Rounding Mode
#[inline]
pub fn frm(&self) -> RoundingMode {
match self.bits.get_bits(5..8) {
0b000 => RoundingMode::RoundToNearestEven,
0b001 => RoundingMode::RoundTowardsZero,
0b010 => RoundingMode::RoundDown,
0b011 => RoundingMode::RoundUp,
0b100 => RoundingMode::RoundToNearestMaxMagnitude,
_ => RoundingMode::Invalid,
}
}
}
read_csr!(0x003, __read_fcsr);
write_csr!(0x003, __write_fcsr);
clear!(0x003, __clear_fcsr);
/// Reads the CSR
#[inline]
pub fn read() -> FCSR {
FCSR { bits: unsafe{ _read() as u32 } }
}
/// Writes the CSR
#[inline]
pub unsafe fn set_rounding_mode(frm: RoundingMode) {
let old = read();
let bits = ((frm as u32) << 5) | old.fflags().0;
_write(bits as usize);
}
/// Resets `fflags` field bits
#[inline]
pub unsafe fn clear_flags() {
let mask = 0b11111;
_clear(mask);
}
/// Resets `fflags` field bit
#[inline]
pub unsafe fn clear_flag(flag: Flag) {
_clear(flag as usize);
}

View File

@ -1,82 +0,0 @@
macro_rules! reg {
(
$addr:expr, $csrl:ident, $csrh:ident, $readf:ident, $writef:ident
) => {
/// Performance-monitoring counter
pub mod $csrl {
read_csr_as_usize!($addr, $readf);
read_composite_csr!(super::$csrh::read(), read());
}
}
}
macro_rules! regh {
(
$addr:expr, $csrh:ident, $readf:ident, $writef:ident
) => {
/// Upper 32 bits of performance-monitoring counter (RV32I only)
pub mod $csrh {
read_csr_as_usize_rv32!($addr, $readf);
}
}
}
reg!(0xC03, hpmcounter3, hpmcounter3h, __read_hpmcounter3, __write_hpmcounter3);
reg!(0xC04, hpmcounter4, hpmcounter4h, __read_hpmcounter4, __write_hpmcounter4);
reg!(0xC05, hpmcounter5, hpmcounter5h, __read_hpmcounter5, __write_hpmcounter5);
reg!(0xC06, hpmcounter6, hpmcounter6h, __read_hpmcounter6, __write_hpmcounter6);
reg!(0xC07, hpmcounter7, hpmcounter7h, __read_hpmcounter7, __write_hpmcounter7);
reg!(0xC08, hpmcounter8, hpmcounter8h, __read_hpmcounter8, __write_hpmcounter8);
reg!(0xC09, hpmcounter9, hpmcounter9h, __read_hpmcounter9, __write_hpmcounter9);
reg!(0xC0A, hpmcounter10, hpmcounter10h, __read_hpmcounter10, __write_hpmcounter10);
reg!(0xC0B, hpmcounter11, hpmcounter11h, __read_hpmcounter11, __write_hpmcounter11);
reg!(0xC0C, hpmcounter12, hpmcounter12h, __read_hpmcounter12, __write_hpmcounter12);
reg!(0xC0D, hpmcounter13, hpmcounter13h, __read_hpmcounter13, __write_hpmcounter13);
reg!(0xC0E, hpmcounter14, hpmcounter14h, __read_hpmcounter14, __write_hpmcounter14);
reg!(0xC0F, hpmcounter15, hpmcounter15h, __read_hpmcounter15, __write_hpmcounter15);
reg!(0xC10, hpmcounter16, hpmcounter16h, __read_hpmcounter16, __write_hpmcounter16);
reg!(0xC11, hpmcounter17, hpmcounter17h, __read_hpmcounter17, __write_hpmcounter17);
reg!(0xC12, hpmcounter18, hpmcounter18h, __read_hpmcounter18, __write_hpmcounter18);
reg!(0xC13, hpmcounter19, hpmcounter19h, __read_hpmcounter19, __write_hpmcounter19);
reg!(0xC14, hpmcounter20, hpmcounter20h, __read_hpmcounter20, __write_hpmcounter20);
reg!(0xC15, hpmcounter21, hpmcounter21h, __read_hpmcounter21, __write_hpmcounter21);
reg!(0xC16, hpmcounter22, hpmcounter22h, __read_hpmcounter22, __write_hpmcounter22);
reg!(0xC17, hpmcounter23, hpmcounter23h, __read_hpmcounter23, __write_hpmcounter23);
reg!(0xC18, hpmcounter24, hpmcounter24h, __read_hpmcounter24, __write_hpmcounter24);
reg!(0xC19, hpmcounter25, hpmcounter25h, __read_hpmcounter25, __write_hpmcounter25);
reg!(0xC1A, hpmcounter26, hpmcounter26h, __read_hpmcounter26, __write_hpmcounter26);
reg!(0xC1B, hpmcounter27, hpmcounter27h, __read_hpmcounter27, __write_hpmcounter27);
reg!(0xC1C, hpmcounter28, hpmcounter28h, __read_hpmcounter28, __write_hpmcounter28);
reg!(0xC1D, hpmcounter29, hpmcounter29h, __read_hpmcounter29, __write_hpmcounter29);
reg!(0xC1E, hpmcounter30, hpmcounter30h, __read_hpmcounter30, __write_hpmcounter30);
reg!(0xC1F, hpmcounter31, hpmcounter31h, __read_hpmcounter31, __write_hpmcounter31);
regh!(0xC83, hpmcounter3h, __read_hpmcounter3h, __write_hpmcounter3h);
regh!(0xC84, hpmcounter4h, __read_hpmcounter4h, __write_hpmcounter4h);
regh!(0xC85, hpmcounter5h, __read_hpmcounter5h, __write_hpmcounter5h);
regh!(0xC86, hpmcounter6h, __read_hpmcounter6h, __write_hpmcounter6h);
regh!(0xC87, hpmcounter7h, __read_hpmcounter7h, __write_hpmcounter7h);
regh!(0xC88, hpmcounter8h, __read_hpmcounter8h, __write_hpmcounter8h);
regh!(0xC89, hpmcounter9h, __read_hpmcounter9h, __write_hpmcounter9h);
regh!(0xC8A, hpmcounter10h, __read_hpmcounter10h, __write_hpmcounter10h);
regh!(0xC8B, hpmcounter11h, __read_hpmcounter11h, __write_hpmcounter11h);
regh!(0xC8C, hpmcounter12h, __read_hpmcounter12h, __write_hpmcounter12h);
regh!(0xC8D, hpmcounter13h, __read_hpmcounter13h, __write_hpmcounter13h);
regh!(0xC8E, hpmcounter14h, __read_hpmcounter14h, __write_hpmcounter14h);
regh!(0xC8F, hpmcounter15h, __read_hpmcounter15h, __write_hpmcounter15h);
regh!(0xC90, hpmcounter16h, __read_hpmcounter16h, __write_hpmcounter16h);
regh!(0xC91, hpmcounter17h, __read_hpmcounter17h, __write_hpmcounter17h);
regh!(0xC92, hpmcounter18h, __read_hpmcounter18h, __write_hpmcounter18h);
regh!(0xC93, hpmcounter19h, __read_hpmcounter19h, __write_hpmcounter19h);
regh!(0xC94, hpmcounter20h, __read_hpmcounter20h, __write_hpmcounter20h);
regh!(0xC95, hpmcounter21h, __read_hpmcounter21h, __write_hpmcounter21h);
regh!(0xC96, hpmcounter22h, __read_hpmcounter22h, __write_hpmcounter22h);
regh!(0xC97, hpmcounter23h, __read_hpmcounter23h, __write_hpmcounter23h);
regh!(0xC98, hpmcounter24h, __read_hpmcounter24h, __write_hpmcounter24h);
regh!(0xC99, hpmcounter25h, __read_hpmcounter25h, __write_hpmcounter25h);
regh!(0xC9A, hpmcounter26h, __read_hpmcounter26h, __write_hpmcounter26h);
regh!(0xC9B, hpmcounter27h, __read_hpmcounter27h, __write_hpmcounter27h);
regh!(0xC9C, hpmcounter28h, __read_hpmcounter28h, __write_hpmcounter28h);
regh!(0xC9D, hpmcounter29h, __read_hpmcounter29h, __write_hpmcounter29h);
regh!(0xC9E, hpmcounter30h, __read_hpmcounter30h, __write_hpmcounter30h);
regh!(0xC9F, hpmcounter31h, __read_hpmcounter31h, __write_hpmcounter31h);

View File

@ -1,3 +1,5 @@
#![allow(unused_macros)]
macro_rules! read_csr {
($csr_number:expr, $asm_fn: ident) => {
/// Reads the CSR

View File

@ -1,27 +0,0 @@
//! marchid register
use core::num::NonZeroUsize;
/// marchid register
#[derive(Clone, Copy, Debug)]
pub struct Marchid {
bits: NonZeroUsize,
}
impl Marchid {
/// Returns the contents of the register as raw bits
pub fn bits(&self) -> usize {
self.bits.get()
}
}
read_csr!(0xF11, __read_marchid);
/// Reads the CSR
#[inline]
pub fn read() -> Option<Marchid> {
let r = unsafe{ _read() };
// When marchid is hardwired to zero it means that the marchid
// csr isn't implemented.
NonZeroUsize::new(r).map(|bits| Marchid { bits })
}

View File

@ -1,139 +0,0 @@
//! mcause register
/// mcause register
#[derive(Clone, Copy, Debug)]
pub struct Mcause {
bits: usize,
}
/// Trap Cause
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Trap {
Interrupt(Interrupt),
Exception(Exception),
}
/// Interrupt
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Interrupt {
UserSoft,
SupervisorSoft,
MachineSoft,
UserTimer,
SupervisorTimer,
MachineTimer,
UserExternal,
SupervisorExternal,
MachineExternal,
Unknown,
}
/// Exception
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Exception {
InstructionMisaligned,
InstructionFault,
IllegalInstruction,
Breakpoint,
LoadMisaligned,
LoadFault,
StoreMisaligned,
StoreFault,
UserEnvCall,
SupervisorEnvCall,
MachineEnvCall,
InstructionPageFault,
LoadPageFault,
StorePageFault,
Unknown,
}
impl Interrupt {
pub fn from(nr: usize) -> Self {
match nr {
0 => Interrupt::UserSoft,
1 => Interrupt::SupervisorSoft,
3 => Interrupt::MachineSoft,
4 => Interrupt::UserTimer,
5 => Interrupt::SupervisorTimer,
7 => Interrupt::MachineTimer,
8 => Interrupt::UserExternal,
9 => Interrupt::SupervisorExternal,
11 => Interrupt::MachineExternal,
_ => Interrupt::Unknown,
}
}
}
impl Exception {
pub fn from(nr: usize) -> Self {
match nr {
0 => Exception::InstructionMisaligned,
1 => Exception::InstructionFault,
2 => Exception::IllegalInstruction,
3 => Exception::Breakpoint,
4 => Exception::LoadMisaligned,
5 => Exception::LoadFault,
6 => Exception::StoreMisaligned,
7 => Exception::StoreFault,
8 => Exception::UserEnvCall,
9 => Exception::SupervisorEnvCall,
11 => Exception::MachineEnvCall,
12 => Exception::InstructionPageFault,
13 => Exception::LoadPageFault,
15 => Exception::StorePageFault,
_ => Exception::Unknown,
}
}
}
impl Mcause {
/// Returns the contents of the register as raw bits
#[inline]
pub fn bits(&self) -> usize {
self.bits
}
/// Returns the code field
pub fn code(&self) -> usize {
match () {
#[cfg(target_pointer_width = "32")]
() => self.bits & !(1 << 31),
#[cfg(target_pointer_width = "64")]
() => self.bits & !(1 << 63),
#[cfg(target_pointer_width = "128")]
() => self.bits & !(1 << 127),
}
}
/// Trap Cause
#[inline]
pub fn cause(&self) -> Trap {
if self.is_interrupt() {
Trap::Interrupt(Interrupt::from(self.code()))
} else {
Trap::Exception(Exception::from(self.code()))
}
}
/// Is trap cause an interrupt.
#[inline]
pub fn is_interrupt(&self) -> bool {
match () {
#[cfg(target_pointer_width = "32")]
() => self.bits & (1 << 31) == 1 << 31,
#[cfg(target_pointer_width = "64")]
() => self.bits & (1 << 63) == 1 << 63,
#[cfg(target_pointer_width = "128")]
() => self.bits & (1 << 127) == 1 << 127,
}
}
/// Is trap cause an exception.
#[inline]
pub fn is_exception(&self) -> bool {
!self.is_interrupt()
}
}
read_csr_as!(Mcause, 0x342, __read_mcause);

View File

@ -1,4 +0,0 @@
//! mcycle register
read_csr_as_usize!(0xB00, __read_mcycle);
read_composite_csr!(super::mcycleh::read(), read());

View File

@ -1,3 +0,0 @@
//! mcycleh register
read_csr_as_usize_rv32!(0xB80, __read_mcycleh);

View File

@ -1,4 +0,0 @@
//! mepc register
read_csr_as_usize!(0x341, __read_mepc);
write_csr_as_usize!(0x341, __write_mepc);

View File

@ -1,3 +0,0 @@
//! mhartid register
read_csr_as_usize!(0xf14, __read_mhartid);

View File

@ -1,84 +0,0 @@
macro_rules! reg {
(
$addr:expr, $csrl:ident, $csrh:ident, $readf:ident, $writef:ident
) => {
/// Machine performance-monitoring counter
pub mod $csrl {
read_csr_as_usize!($addr, $readf);
write_csr_as_usize!($addr, $writef);
read_composite_csr!(super::$csrh::read(), read());
}
}
}
macro_rules! regh {
(
$addr:expr, $csrh:ident, $readf:ident, $writef:ident
) => {
/// Upper 32 bits of machine performance-monitoring counter (RV32I only)
pub mod $csrh {
read_csr_as_usize_rv32!($addr, $readf);
write_csr_as_usize_rv32!($addr, $writef);
}
}
}
reg!(0xB03, mhpmcounter3, mhpmcounter3h, __read_mhpmcounter3, __write_mhpmcounter3);
reg!(0xB04, mhpmcounter4, mhpmcounter4h, __read_mhpmcounter4, __write_mhpmcounter4);
reg!(0xB05, mhpmcounter5, mhpmcounter5h, __read_mhpmcounter5, __write_mhpmcounter5);
reg!(0xB06, mhpmcounter6, mhpmcounter6h, __read_mhpmcounter6, __write_mhpmcounter6);
reg!(0xB07, mhpmcounter7, mhpmcounter7h, __read_mhpmcounter7, __write_mhpmcounter7);
reg!(0xB08, mhpmcounter8, mhpmcounter8h, __read_mhpmcounter8, __write_mhpmcounter8);
reg!(0xB09, mhpmcounter9, mhpmcounter9h, __read_mhpmcounter9, __write_mhpmcounter9);
reg!(0xB0A, mhpmcounter10, mhpmcounter10h, __read_mhpmcounter10, __write_mhpmcounter10);
reg!(0xB0B, mhpmcounter11, mhpmcounter11h, __read_mhpmcounter11, __write_mhpmcounter11);
reg!(0xB0C, mhpmcounter12, mhpmcounter12h, __read_mhpmcounter12, __write_mhpmcounter12);
reg!(0xB0D, mhpmcounter13, mhpmcounter13h, __read_mhpmcounter13, __write_mhpmcounter13);
reg!(0xB0E, mhpmcounter14, mhpmcounter14h, __read_mhpmcounter14, __write_mhpmcounter14);
reg!(0xB0F, mhpmcounter15, mhpmcounter15h, __read_mhpmcounter15, __write_mhpmcounter15);
reg!(0xB10, mhpmcounter16, mhpmcounter16h, __read_mhpmcounter16, __write_mhpmcounter16);
reg!(0xB11, mhpmcounter17, mhpmcounter17h, __read_mhpmcounter17, __write_mhpmcounter17);
reg!(0xB12, mhpmcounter18, mhpmcounter18h, __read_mhpmcounter18, __write_mhpmcounter18);
reg!(0xB13, mhpmcounter19, mhpmcounter19h, __read_mhpmcounter19, __write_mhpmcounter19);
reg!(0xB14, mhpmcounter20, mhpmcounter20h, __read_mhpmcounter20, __write_mhpmcounter20);
reg!(0xB15, mhpmcounter21, mhpmcounter21h, __read_mhpmcounter21, __write_mhpmcounter21);
reg!(0xB16, mhpmcounter22, mhpmcounter22h, __read_mhpmcounter22, __write_mhpmcounter22);
reg!(0xB17, mhpmcounter23, mhpmcounter23h, __read_mhpmcounter23, __write_mhpmcounter23);
reg!(0xB18, mhpmcounter24, mhpmcounter24h, __read_mhpmcounter24, __write_mhpmcounter24);
reg!(0xB19, mhpmcounter25, mhpmcounter25h, __read_mhpmcounter25, __write_mhpmcounter25);
reg!(0xB1A, mhpmcounter26, mhpmcounter26h, __read_mhpmcounter26, __write_mhpmcounter26);
reg!(0xB1B, mhpmcounter27, mhpmcounter27h, __read_mhpmcounter27, __write_mhpmcounter27);
reg!(0xB1C, mhpmcounter28, mhpmcounter28h, __read_mhpmcounter28, __write_mhpmcounter28);
reg!(0xB1D, mhpmcounter29, mhpmcounter29h, __read_mhpmcounter29, __write_mhpmcounter29);
reg!(0xB1E, mhpmcounter30, mhpmcounter30h, __read_mhpmcounter30, __write_mhpmcounter30);
reg!(0xB1F, mhpmcounter31, mhpmcounter31h, __read_mhpmcounter31, __write_mhpmcounter31);
regh!(0xB83, mhpmcounter3h, __read_mhpmcounter3h, __write_mhpmcounter3h);
regh!(0xB84, mhpmcounter4h, __read_mhpmcounter4h, __write_mhpmcounter4h);
regh!(0xB85, mhpmcounter5h, __read_mhpmcounter5h, __write_mhpmcounter5h);
regh!(0xB86, mhpmcounter6h, __read_mhpmcounter6h, __write_mhpmcounter6h);
regh!(0xB87, mhpmcounter7h, __read_mhpmcounter7h, __write_mhpmcounter7h);
regh!(0xB88, mhpmcounter8h, __read_mhpmcounter8h, __write_mhpmcounter8h);
regh!(0xB89, mhpmcounter9h, __read_mhpmcounter9h, __write_mhpmcounter9h);
regh!(0xB8A, mhpmcounter10h, __read_mhpmcounter10h, __write_mhpmcounter10h);
regh!(0xB8B, mhpmcounter11h, __read_mhpmcounter11h, __write_mhpmcounter11h);
regh!(0xB8C, mhpmcounter12h, __read_mhpmcounter12h, __write_mhpmcounter12h);
regh!(0xB8D, mhpmcounter13h, __read_mhpmcounter13h, __write_mhpmcounter13h);
regh!(0xB8E, mhpmcounter14h, __read_mhpmcounter14h, __write_mhpmcounter14h);
regh!(0xB8F, mhpmcounter15h, __read_mhpmcounter15h, __write_mhpmcounter15h);
regh!(0xB90, mhpmcounter16h, __read_mhpmcounter16h, __write_mhpmcounter16h);
regh!(0xB91, mhpmcounter17h, __read_mhpmcounter17h, __write_mhpmcounter17h);
regh!(0xB92, mhpmcounter18h, __read_mhpmcounter18h, __write_mhpmcounter18h);
regh!(0xB93, mhpmcounter19h, __read_mhpmcounter19h, __write_mhpmcounter19h);
regh!(0xB94, mhpmcounter20h, __read_mhpmcounter20h, __write_mhpmcounter20h);
regh!(0xB95, mhpmcounter21h, __read_mhpmcounter21h, __write_mhpmcounter21h);
regh!(0xB96, mhpmcounter22h, __read_mhpmcounter22h, __write_mhpmcounter22h);
regh!(0xB97, mhpmcounter23h, __read_mhpmcounter23h, __write_mhpmcounter23h);
regh!(0xB98, mhpmcounter24h, __read_mhpmcounter24h, __write_mhpmcounter24h);
regh!(0xB99, mhpmcounter25h, __read_mhpmcounter25h, __write_mhpmcounter25h);
regh!(0xB9A, mhpmcounter26h, __read_mhpmcounter26h, __write_mhpmcounter26h);
regh!(0xB9B, mhpmcounter27h, __read_mhpmcounter27h, __write_mhpmcounter27h);
regh!(0xB9C, mhpmcounter28h, __read_mhpmcounter28h, __write_mhpmcounter28h);
regh!(0xB9D, mhpmcounter29h, __read_mhpmcounter29h, __write_mhpmcounter29h);
regh!(0xB9E, mhpmcounter30h, __read_mhpmcounter30h, __write_mhpmcounter30h);
regh!(0xB9F, mhpmcounter31h, __read_mhpmcounter31h, __write_mhpmcounter31h);

View File

@ -1,41 +0,0 @@
macro_rules! reg {
(
$addr:expr, $csr:ident, $readf:ident, $writef:ident
) => {
/// Machine performance-monitoring event selector
pub mod $csr {
read_csr_as_usize!($addr, $readf);
write_csr_as_usize!($addr, $writef);
}
}
}
reg!(0x323, mhpmevent3, __read_mhpmevent3, __write_mhpmevent3);
reg!(0x324, mhpmevent4, __read_mhpmevent4, __write_mhpmevent4);
reg!(0x325, mhpmevent5, __read_mhpmevent5, __write_mhpmevent5);
reg!(0x326, mhpmevent6, __read_mhpmevent6, __write_mhpmevent6);
reg!(0x327, mhpmevent7, __read_mhpmevent7, __write_mhpmevent7);
reg!(0x328, mhpmevent8, __read_mhpmevent8, __write_mhpmevent8);
reg!(0x329, mhpmevent9, __read_mhpmevent9, __write_mhpmevent9);
reg!(0x32A, mhpmevent10, __read_mhpmevent10, __write_mhpmevent10);
reg!(0x32B, mhpmevent11, __read_mhpmevent11, __write_mhpmevent11);
reg!(0x32C, mhpmevent12, __read_mhpmevent12, __write_mhpmevent12);
reg!(0x32D, mhpmevent13, __read_mhpmevent13, __write_mhpmevent13);
reg!(0x32E, mhpmevent14, __read_mhpmevent14, __write_mhpmevent14);
reg!(0x32F, mhpmevent15, __read_mhpmevent15, __write_mhpmevent15);
reg!(0x330, mhpmevent16, __read_mhpmevent16, __write_mhpmevent16);
reg!(0x331, mhpmevent17, __read_mhpmevent17, __write_mhpmevent17);
reg!(0x332, mhpmevent18, __read_mhpmevent18, __write_mhpmevent18);
reg!(0x333, mhpmevent19, __read_mhpmevent19, __write_mhpmevent19);
reg!(0x334, mhpmevent20, __read_mhpmevent20, __write_mhpmevent20);
reg!(0x335, mhpmevent21, __read_mhpmevent21, __write_mhpmevent21);
reg!(0x336, mhpmevent22, __read_mhpmevent22, __write_mhpmevent22);
reg!(0x337, mhpmevent23, __read_mhpmevent23, __write_mhpmevent23);
reg!(0x338, mhpmevent24, __read_mhpmevent24, __write_mhpmevent24);
reg!(0x339, mhpmevent25, __read_mhpmevent25, __write_mhpmevent25);
reg!(0x33A, mhpmevent26, __read_mhpmevent26, __write_mhpmevent26);
reg!(0x33B, mhpmevent27, __read_mhpmevent27, __write_mhpmevent27);
reg!(0x33C, mhpmevent28, __read_mhpmevent28, __write_mhpmevent28);
reg!(0x33D, mhpmevent29, __read_mhpmevent29, __write_mhpmevent29);
reg!(0x33E, mhpmevent30, __read_mhpmevent30, __write_mhpmevent30);
reg!(0x33F, mhpmevent31, __read_mhpmevent31, __write_mhpmevent31);

View File

@ -1,103 +0,0 @@
//! mie register
use bit_field::BitField;
/// mie register
#[derive(Clone, Copy, Debug)]
pub struct Mie {
bits: usize,
}
impl Mie {
/// Returns the contents of the register as raw bits
#[inline]
pub fn bits(&self) -> usize {
self.bits
}
/// User Software Interrupt Enable
#[inline]
pub fn usoft(&self) -> bool {
self.bits.get_bit(0)
}
/// Supervisor Software Interrupt Enable
#[inline]
pub fn ssoft(&self) -> bool {
self.bits.get_bit(1)
}
/// Machine Software Interrupt Enable
#[inline]
pub fn msoft(&self) -> bool {
self.bits.get_bit(3)
}
/// User Timer Interrupt Enable
#[inline]
pub fn utimer(&self) -> bool {
self.bits.get_bit(4)
}
/// Supervisor Timer Interrupt Enable
#[inline]
pub fn stimer(&self) -> bool {
self.bits.get_bit(5)
}
/// Machine Timer Interrupt Enable
#[inline]
pub fn mtimer(&self) -> bool {
self.bits.get_bit(7)
}
/// User External Interrupt Enable
#[inline]
pub fn uext(&self) -> bool {
self.bits.get_bit(8)
}
/// Supervisor External Interrupt Enable
#[inline]
pub fn sext(&self) -> bool {
self.bits.get_bit(9)
}
/// Machine External Interrupt Enable
#[inline]
pub fn mext(&self) -> bool {
self.bits.get_bit(11)
}
}
read_csr_as!(Mie, 0x304, __read_mie);
set!(0x304, __set_mie);
clear!(0x304, __clear_mie);
set_clear_csr!(
/// User Software Interrupt Enable
, set_usoft, clear_usoft, 1 << 0);
set_clear_csr!(
/// Supervisor Software Interrupt Enable
, set_ssoft, clear_ssoft, 1 << 1);
set_clear_csr!(
/// Machine Software Interrupt Enable
, set_msoft, clear_msoft, 1 << 3);
set_clear_csr!(
/// User Timer Interrupt Enable
, set_utimer, clear_utimer, 1 << 4);
set_clear_csr!(
/// Supervisor Timer Interrupt Enable
, set_stimer, clear_stimer, 1 << 5);
set_clear_csr!(
/// Machine Timer Interrupt Enable
, set_mtimer, clear_mtimer, 1 << 7);
set_clear_csr!(
/// User External Interrupt Enable
, set_uext, clear_uext, 1 << 8);
set_clear_csr!(
/// Supervisor External Interrupt Enable
, set_sext, clear_sext, 1 << 9);
set_clear_csr!(
/// Machine External Interrupt Enable
, set_mext, clear_mext, 1 << 11);

View File

@ -1,27 +0,0 @@
//! mimpid register
use core::num::NonZeroUsize;
/// mimpid register
#[derive(Clone, Copy, Debug)]
pub struct Mimpid {
bits: NonZeroUsize,
}
impl Mimpid {
/// Returns the contents of the register as raw bits
pub fn bits(&self) -> usize {
self.bits.get()
}
}
read_csr!(0xF11, __read_mimpid);
/// Reads the CSR
#[inline]
pub fn read() -> Option<Mimpid> {
let r = unsafe{ _read() };
// When mimpid is hardwired to zero it means that the mimpid
// csr isn't implemented.
NonZeroUsize::new(r).map(|bits| Mimpid { bits })
}

View File

@ -1,4 +0,0 @@
//! minstret register
read_csr_as_usize!(0xB02, __read_minstret);
read_composite_csr!(super::minstreth::read(), read());

View File

@ -1,3 +0,0 @@
//! minstreth register
read_csr_as_usize_rv32!(0xB82, __read_minstreth);

View File

@ -1,100 +0,0 @@
//! mip register
use bit_field::BitField;
/// mip register
#[derive(Clone, Copy, Debug)]
pub struct Mip {
bits: usize,
}
impl Mip {
/// Returns the contents of the register as raw bits
#[inline]
pub fn bits(&self) -> usize {
self.bits
}
/// User Software Interrupt Pending
#[inline]
pub fn usoft(&self) -> bool {
self.bits.get_bit(0)
}
/// Supervisor Software Interrupt Pending
#[inline]
pub fn ssoft(&self) -> bool {
self.bits.get_bit(1)
}
/// Machine Software Interrupt Pending
#[inline]
pub fn msoft(&self) -> bool {
self.bits.get_bit(3)
}
/// User Timer Interrupt Pending
#[inline]
pub fn utimer(&self) -> bool {
self.bits.get_bit(4)
}
/// Supervisor Timer Interrupt Pending
#[inline]
pub fn stimer(&self) -> bool {
self.bits.get_bit(5)
}
/// Machine Timer Interrupt Pending
#[inline]
pub fn mtimer(&self) -> bool {
self.bits.get_bit(7)
}
/// User External Interrupt Pending
#[inline]
pub fn uext(&self) -> bool {
self.bits.get_bit(8)
}
/// Supervisor External Interrupt Pending
#[inline]
pub fn sext(&self) -> bool {
self.bits.get_bit(9)
}
/// Machine External Interrupt Pending
#[inline]
pub fn mext(&self) -> bool {
self.bits.get_bit(11)
}
}
read_csr_as!(Mip, 0x344, __read_mip);
set!(0x344, __set_mip);
clear!(0x344, __clear_mip);
set_clear_csr!(
/// User Software Interrupt Pending
, set_usoft, clear_usoft, 1 << 0);
set_clear_csr!(
/// Supervisor Software Interrupt Pending
, set_ssoft, clear_ssoft, 1 << 1);
set_clear_csr!(
/// Machine Software Interrupt Pending
, set_msoft, clear_msoft, 1 << 3);
set_clear_csr!(
/// User Timer Interrupt Pending
, set_utimer, clear_utimer, 1 << 4);
set_clear_csr!(
/// Supervisor Timer Interrupt Pending
, set_stimer, clear_stimer, 1 << 5);
set_clear_csr!(
/// Machine Timer Interrupt Pending
, set_mtimer, clear_mtimer, 1 << 7);
set_clear_csr!(
/// User External Interrupt Pending
, set_uext, clear_uext, 1 << 8);
set_clear_csr!(
/// Supervisor External Interrupt Pending
, set_sext, clear_sext, 1 << 9);

View File

@ -1,60 +0,0 @@
//! misa register
use core::num::NonZeroUsize;
/// misa register
#[derive(Clone, Copy, Debug)]
pub struct Misa {
bits: NonZeroUsize,
}
/// Machine XLEN
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum MXL {
XLEN32,
XLEN64,
XLEN128,
}
impl Misa {
/// Returns the contents of the register as raw bits
pub fn bits(&self) -> usize {
self.bits.get()
}
/// Returns the machine xlen.
pub fn mxl(&self) -> MXL {
let value = match () {
#[cfg(target_pointer_width = "32")]
() => (self.bits() >> 30) as u8,
#[cfg(target_pointer_width = "64")]
() => (self.bits() >> 62) as u8,
};
match value {
1 => MXL::XLEN32,
2 => MXL::XLEN64,
3 => MXL::XLEN128,
_ => unreachable!(),
}
}
/// Returns true when the atomic extension is implemented.
pub fn has_extension(&self, extension: char) -> bool {
let bit = extension as u8 - 65;
if bit > 25 {
return false;
}
self.bits() & (1 << bit) == (1 << bit)
}
}
read_csr!(0x301, __read_misa);
/// Reads the CSR
#[inline]
pub fn read() -> Option<Misa> {
let r = unsafe{ _read() };
// When misa is hardwired to zero it means that the misa csr
// isn't implemented.
NonZeroUsize::new(r).map(|bits| Misa { bits })
}

View File

@ -1,114 +1,9 @@
//! RISC-V CSR's
//!
//! The following registers are not available on 64-bit implementations.
//!
//! - cycleh
//! - timeh
//! - instreth
//! - hpmcounter[3-31]h
//! - mcycleh
//! - minstreth
//! - mhpmcounter[3-31]h
//! VexRiscv Control and Status Registers
#[macro_use]
mod macros;
// User Trap Setup
pub mod ustatus;
pub mod uie;
pub mod utvec;
// User Trap Handling
pub mod uscratch;
pub mod uepc;
pub mod ucause;
pub mod utval;
pub mod uip;
// User Floating-Point CSRs
// TODO: frm, fflags
pub mod fcsr;
// User Counter/Timers
// TODO: cycle[h], instret[h]
pub mod time;
mod hpmcounterx;
pub use self::hpmcounterx::*;
pub mod timeh;
// Supervisor Trap Setup
// TODO: sedeleg, sideleg
pub mod sstatus;
pub mod sie;
pub mod stvec;
// TODO: scounteren
// Supervisor Trap Handling
pub mod sscratch;
pub mod sepc;
pub mod scause;
pub mod stval;
pub mod sip;
// Supervisor Protection and Translation
pub mod satp;
// Machine Information Registers
pub mod mvendorid;
pub mod marchid;
pub mod mimpid;
pub mod mhartid;
// Machine Trap Setup
pub mod mstatus;
pub mod misa;
// TODO: medeleg, mideleg
pub mod mie;
pub mod mtvec;
// TODO: mcounteren
// Machine Trap Handling
pub mod mscratch;
pub mod mepc;
pub mod mcause;
pub mod mtval;
pub mod mip;
// Machine Protection and Translation
mod pmpcfgx;
pub use self::pmpcfgx::*;
mod pmpaddrx;
pub use self::pmpaddrx::*;
// Machine Counter/Timers
pub mod mcycle;
pub mod minstret;
mod mhpmcounterx;
pub use self::mhpmcounterx::*;
pub mod mcycleh;
pub mod minstreth;
// Machine Counter Setup
mod mhpmeventx;
pub use self::mhpmeventx::*;
// TODO: Debug/Trace Registers (shared with Debug Mode)
// TODO: Debug Mode Registers
// Vexriscv Registers
// VexRiscv Registers
pub mod vdci;
pub mod vmim;
pub mod vmip;

View File

@ -1,4 +0,0 @@
//! mscratch register
read_csr_as_usize!(0x340, __read_mscratch);
write_csr_as_usize!(0x340, __write_mscratch);

View File

@ -1,200 +0,0 @@
//! mstatus register
// TODO: Virtualization, Memory Privilege and Extension Context Fields
use bit_field::BitField;
use core::mem::size_of;
/// mstatus register
#[derive(Clone, Copy, Debug)]
pub struct Mstatus {
bits: usize,
}
/// Additional extension state
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum XS {
/// All off
AllOff = 0,
/// None dirty or clean, some on
NoneDirtyOrClean = 1,
/// None dirty, some clean
NoneDirtySomeClean = 2,
/// Some dirty
SomeDirty = 3,
}
/// Floating-point extension state
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum FS {
Off = 0,
Initial = 1,
Clean = 2,
Dirty = 3,
}
/// Machine Previous Privilege Mode
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum MPP {
Machine = 3,
Supervisor = 1,
User = 0,
}
/// Supervisor Previous Privilege Mode
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum SPP {
Supervisor = 1,
User = 0,
}
impl Mstatus {
/// User Interrupt Enable
#[inline]
pub fn uie(&self) -> bool {
self.bits.get_bit(0)
}
/// Supervisor Interrupt Enable
#[inline]
pub fn sie(&self) -> bool {
self.bits.get_bit(1)
}
/// Machine Interrupt Enable
#[inline]
pub fn mie(&self) -> bool {
self.bits.get_bit(3)
}
/// User Previous Interrupt Enable
#[inline]
pub fn upie(&self) -> bool {
self.bits.get_bit(4)
}
/// Supervisor Previous Interrupt Enable
#[inline]
pub fn spie(&self) -> bool {
self.bits.get_bit(5)
}
/// Machine Previous Interrupt Enable
#[inline]
pub fn mpie(&self) -> bool {
self.bits.get_bit(7)
}
/// Supervisor Previous Privilege Mode
#[inline]
pub fn spp(&self) -> SPP {
match self.bits.get_bit(8) {
true => SPP::Supervisor,
false => SPP::User,
}
}
/// Machine Previous Privilege Mode
#[inline]
pub fn mpp(&self) -> MPP {
match self.bits.get_bits(11..13) {
0b00 => MPP::User,
0b01 => MPP::Supervisor,
0b11 => MPP::Machine,
_ => unreachable!(),
}
}
/// Floating-point extension state
///
/// Encodes the status of the floating-point unit,
/// including the CSR `fcsr` and floating-point data registers `f0f31`.
#[inline]
pub fn fs(&self) -> FS {
match self.bits.get_bits(13..15) {
0b00 => FS::Off,
0b01 => FS::Initial,
0b10 => FS::Clean,
0b11 => FS::Dirty,
_ => unreachable!(),
}
}
/// Additional extension state
///
/// Encodes the status of additional user-mode extensions and associated state.
#[inline]
pub fn xs(&self) -> XS {
match self.bits.get_bits(15..17) {
0b00 => XS::AllOff,
0b01 => XS::NoneDirtyOrClean,
0b10 => XS::NoneDirtySomeClean,
0b11 => XS::SomeDirty,
_ => unreachable!(),
}
}
/// Whether either the FS field or XS field
/// signals the presence of some dirty state
#[inline]
pub fn sd(&self) -> bool {
self.bits.get_bit(size_of::<usize>() * 8 - 1)
}
}
read_csr_as!(Mstatus, 0x300, __read_mstatus);
write_csr!(0x300, __write_mstatus);
set!(0x300, __set_mstatus);
clear!(0x300, __clear_mstatus);
set_clear_csr!(
/// User Interrupt Enable
, set_uie, clear_uie, 1 << 0);
set_clear_csr!(
/// Supervisor Interrupt Enable
, set_sie, clear_sie, 1 << 1);
set_clear_csr!(
/// Machine Interrupt Enable
, set_mie, clear_mie, 1 << 3);
set_csr!(
/// User Previous Interrupt Enable
, set_upie, 1 << 4);
set_csr!(
/// Supervisor Previous Interrupt Enable
, set_spie, 1 << 5);
set_csr!(
/// Machine Previous Interrupt Enable
, set_mpie, 1 << 7);
/// Supervisor Previous Privilege Mode
#[inline]
pub unsafe fn set_spp(spp: SPP) {
match spp {
SPP::Supervisor => _set(1 << 8),
SPP::User => _clear(1 << 8),
}
}
/// Machine Previous Privilege Mode
#[inline]
pub unsafe fn set_mpp(mpp: MPP) {
let mut value = _read();
value.set_bits(11..13, mpp as usize);
_write(value);
}
/// Floating-point extension state
#[inline]
pub unsafe fn set_fs(fs: FS) {
let mut value = _read();
value.set_bits(13..15, fs as usize);
_write(value);
}

View File

@ -1,3 +0,0 @@
//! mtval register
read_csr_as_usize!(0x343, __read_mtval);

View File

@ -1,47 +0,0 @@
//! mtvec register
/// mtvec register
#[derive(Clone, Copy, Debug)]
pub struct Mtvec {
bits: usize,
}
/// Trap mode
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum TrapMode {
Direct = 0,
Vectored = 1,
}
impl Mtvec {
/// Returns the contents of the register as raw bits
pub fn bits(&self) -> usize {
self.bits
}
/// Returns the trap-vector base-address
pub fn address(&self) -> usize {
self.bits - (self.bits & 0b11)
}
/// Returns the trap-vector mode
pub fn trap_mode(&self) -> TrapMode {
let mode = self.bits & 0b11;
match mode {
0 => TrapMode::Direct,
1 => TrapMode::Vectored,
_ => unimplemented!()
}
}
}
read_csr_as!(Mtvec, 0x305, __read_mtvec);
write_csr!(0x305, __write_mtvec);
/// Writes the CSR
#[inline]
pub unsafe fn write(addr: usize, mode: TrapMode) {
let bits = addr + mode as usize;
_write(bits);
}

View File

@ -1,32 +0,0 @@
//! mvendorid register
use core::num::NonZeroUsize;
/// mvendorid register
#[derive(Clone, Copy, Debug)]
pub struct Mvendorid {
bits: NonZeroUsize,
}
impl Mvendorid {
/// Returns the contents of the register as raw bits
pub fn bits(&self) -> usize {
self.bits.get()
}
/// Returns the JEDEC manufacturer ID
pub fn jedec_manufacturer(&self) -> usize {
self.bits() >> 7
}
}
read_csr!(0xF11, __read_mvendorid);
/// Reads the CSR
#[inline]
pub fn read() -> Option<Mvendorid> {
let r = unsafe{ _read() };
// When mvendorid is hardwired to zero it means that the mvendorid
// csr isn't implemented.
NonZeroUsize::new(r).map(|bits| Mvendorid { bits })
}

View File

@ -1,28 +0,0 @@
macro_rules! reg {
(
$addr:expr, $csr:ident, $readf:ident, $writef:ident
) => {
/// Physical memory protection address register
pub mod $csr {
read_csr_as_usize!($addr, $readf);
write_csr_as_usize!($addr, $writef);
}
}
}
reg!(0x3B0, pmpaddr0, __read_pmpaddr0, __write_pmpaddr0);
reg!(0x3B1, pmpaddr1, __read_pmpaddr1, __write_pmpaddr1);
reg!(0x3B2, pmpaddr2, __read_pmpaddr2, __write_pmpaddr2);
reg!(0x3B3, pmpaddr3, __read_pmpaddr3, __write_pmpaddr3);
reg!(0x3B4, pmpaddr4, __read_pmpaddr4, __write_pmpaddr4);
reg!(0x3B5, pmpaddr5, __read_pmpaddr5, __write_pmpaddr5);
reg!(0x3B6, pmpaddr6, __read_pmpaddr6, __write_pmpaddr6);
reg!(0x3B7, pmpaddr7, __read_pmpaddr7, __write_pmpaddr7);
reg!(0x3B8, pmpaddr8, __read_pmpaddr8, __write_pmpaddr8);
reg!(0x3B9, pmpaddr9, __read_pmpaddr9, __write_pmpaddr9);
reg!(0x3BA, pmpaddr10, __read_pmpaddr10, __write_pmpaddr10);
reg!(0x3BB, pmpaddr11, __read_pmpaddr11, __write_pmpaddr11);
reg!(0x3BC, pmpaddr12, __read_pmpaddr12, __write_pmpaddr12);
reg!(0x3BD, pmpaddr13, __read_pmpaddr13, __write_pmpaddr13);
reg!(0x3BE, pmpaddr14, __read_pmpaddr14, __write_pmpaddr14);
reg!(0x3BF, pmpaddr15, __read_pmpaddr15, __write_pmpaddr15);

View File

@ -1,23 +0,0 @@
/// Physical memory protection configuration
pub mod pmpcfg0 {
read_csr_as_usize!(0x3A0, __read_pmpcfg0);
write_csr_as_usize!(0x3A0, __write_pmpcfg0);
}
/// Physical memory protection configuration, RV32 only
pub mod pmpcfg1 {
read_csr_as_usize_rv32!(0x3A1, __read_pmpcfg1);
write_csr_as_usize_rv32!(0x3A1, __write_pmpcfg1);
}
/// Physical memory protection configuration
pub mod pmpcfg2 {
read_csr_as_usize!(0x3A2, __read_pmpcfg2);
write_csr_as_usize!(0x3A2, __write_pmpcfg2);
}
/// Physical memory protection configuration, RV32 only
pub mod pmpcfg3 {
read_csr_as_usize_rv32!(0x3A3, __read_pmpcfg3);
write_csr_as_usize_rv32!(0x3A3, __write_pmpcfg3);
}

View File

@ -1,110 +0,0 @@
//! satp register
#[cfg(riscv)]
use bit_field::BitField;
/// satp register
#[derive(Clone, Copy, Debug)]
pub struct Satp {
bits: usize,
}
impl Satp {
/// Returns the contents of the register as raw bits
#[inline]
pub fn bits(&self) -> usize {
self.bits
}
/// Current address-translation scheme
#[inline]
#[cfg(riscv32)]
pub fn mode(&self) -> Mode {
match self.bits.get_bit(31) {
false => Mode::Bare,
true => Mode::Sv32,
}
}
/// Current address-translation scheme
#[inline]
#[cfg(riscv64)]
pub fn mode(&self) -> Mode {
match self.bits.get_bits(60..64) {
0 => Mode::Bare,
8 => Mode::Sv39,
9 => Mode::Sv48,
10 => Mode::Sv57,
11 => Mode::Sv64,
_ => unreachable!(),
}
}
/// Address space identifier
#[inline]
#[cfg(riscv32)]
pub fn asid(&self) -> usize {
self.bits.get_bits(22..31)
}
/// Address space identifier
#[inline]
#[cfg(riscv64)]
pub fn asid(&self) -> usize {
self.bits.get_bits(44..60)
}
/// Physical page number
#[inline]
#[cfg(riscv32)]
pub fn ppn(&self) -> usize {
self.bits.get_bits(0..22)
}
/// Physical page number
#[inline]
#[cfg(riscv64)]
pub fn ppn(&self) -> usize {
self.bits.get_bits(0..44)
}
}
#[cfg(riscv32)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Mode {
Bare = 0,
Sv32 = 1,
}
#[cfg(riscv64)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Mode {
Bare = 0,
Sv39 = 8,
Sv48 = 9,
Sv57 = 10,
Sv64 = 11,
}
read_csr_as!(Satp, 0x180, __read_satp);
write_csr_as_usize!(0x180, __write_satp);
#[inline]
#[cfg(riscv32)]
pub unsafe fn set(mode: Mode, asid: usize, ppn: usize) {
let mut bits = 0usize;
bits.set_bits(31..32, mode as usize);
bits.set_bits(22..31, asid);
bits.set_bits(0..22, ppn);
_write(bits);
}
#[inline]
#[cfg(riscv64)]
pub unsafe fn set(mode: Mode, asid: usize, ppn: usize) {
let mut bits = 0usize;
bits.set_bits(60..64, mode as usize);
bits.set_bits(44..60, asid);
bits.set_bits(0..44, ppn);
_write(bits);
}

View File

@ -1,117 +0,0 @@
//! scause register
use bit_field::BitField;
use core::mem::size_of;
/// scause register
#[derive(Clone, Copy)]
pub struct Scause {
bits: usize,
}
/// Trap Cause
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Trap {
Interrupt(Interrupt),
Exception(Exception),
}
/// Interrupt
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Interrupt {
UserSoft,
SupervisorSoft,
UserTimer,
SupervisorTimer,
UserExternal,
SupervisorExternal,
Unknown,
}
/// Exception
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Exception {
InstructionMisaligned,
InstructionFault,
IllegalInstruction,
Breakpoint,
LoadFault,
StoreMisaligned,
StoreFault,
UserEnvCall,
InstructionPageFault,
LoadPageFault,
StorePageFault,
Unknown,
}
impl Interrupt {
pub fn from(nr: usize) -> Self {
match nr {
0 => Interrupt::UserSoft,
1 => Interrupt::SupervisorSoft,
4 => Interrupt::UserTimer,
5 => Interrupt::SupervisorTimer,
8 => Interrupt::UserExternal,
9 => Interrupt::SupervisorExternal,
_ => Interrupt::Unknown,
}
}
}
impl Exception {
pub fn from(nr: usize) -> Self {
match nr {
0 => Exception::InstructionMisaligned,
1 => Exception::InstructionFault,
2 => Exception::IllegalInstruction,
3 => Exception::Breakpoint,
5 => Exception::LoadFault,
6 => Exception::StoreMisaligned,
7 => Exception::StoreFault,
8 => Exception::UserEnvCall,
12 => Exception::InstructionPageFault,
13 => Exception::LoadPageFault,
15 => Exception::StorePageFault,
_ => Exception::Unknown,
}
}
}
impl Scause {
/// Returns the contents of the register as raw bits
#[inline]
pub fn bits(&self) -> usize {
self.bits
}
/// Returns the code field
pub fn code(&self) -> usize {
let bit = 1 << (size_of::<usize>() * 8 - 1);
self.bits & !bit
}
/// Trap Cause
#[inline]
pub fn cause(&self) -> Trap {
if self.is_interrupt() {
Trap::Interrupt(Interrupt::from(self.code()))
} else {
Trap::Exception(Exception::from(self.code()))
}
}
/// Is trap cause an interrupt.
#[inline]
pub fn is_interrupt(&self) -> bool {
self.bits.get_bit(size_of::<usize>() * 8 - 1)
}
/// Is trap cause an exception.
#[inline]
pub fn is_exception(&self) -> bool {
!self.is_interrupt()
}
}
read_csr_as!(Scause, 0x142, __read_scause);

View File

@ -1,4 +0,0 @@
//! sepc register
read_csr_as_usize!(0x141, __read_sepc);
write_csr_as_usize!(0x141, __write_sepc);

View File

@ -1,76 +0,0 @@
//! sie register
use bit_field::BitField;
/// sie register
#[derive(Clone, Copy, Debug)]
pub struct Sie {
bits: usize,
}
impl Sie {
/// Returns the contents of the register as raw bits
#[inline]
pub fn bits(&self) -> usize {
self.bits
}
/// User Software Interrupt Enable
#[inline]
pub fn usoft(&self) -> bool {
self.bits.get_bit(0)
}
/// Supervisor Software Interrupt Enable
#[inline]
pub fn ssoft(&self) -> bool {
self.bits.get_bit(1)
}
/// User Timer Interrupt Enable
#[inline]
pub fn utimer(&self) -> bool {
self.bits.get_bit(4)
}
/// Supervisor Timer Interrupt Enable
#[inline]
pub fn stimer(&self) -> bool {
self.bits.get_bit(5)
}
/// User External Interrupt Enable
#[inline]
pub fn uext(&self) -> bool {
self.bits.get_bit(8)
}
/// Supervisor External Interrupt Enable
#[inline]
pub fn sext(&self) -> bool {
self.bits.get_bit(9)
}
}
read_csr_as!(Sie, 0x104, __read_sie);
set!(0x104, __set_sie);
clear!(0x104, __clear_sie);
set_clear_csr!(
/// User Software Interrupt Enable
, set_usoft, clear_usoft, 1 << 0);
set_clear_csr!(
/// Supervisor Software Interrupt Enable
, set_ssoft, clear_ssoft, 1 << 1);
set_clear_csr!(
/// User Timer Interrupt Enable
, set_utimer, clear_utimer, 1 << 4);
set_clear_csr!(
/// Supervisor Timer Interrupt Enable
, set_stimer, clear_stimer, 1 << 5);
set_clear_csr!(
/// User External Interrupt Enable
, set_uext, clear_uext, 1 << 8);
set_clear_csr!(
/// Supervisor External Interrupt Enable
, set_sext, clear_sext, 1 << 9);

View File

@ -1,55 +0,0 @@
//! sip register
use bit_field::BitField;
/// sip register
#[derive(Clone, Copy, Debug)]
pub struct Sip {
bits: usize,
}
impl Sip {
/// Returns the contents of the register as raw bits
#[inline]
pub fn bits(&self) -> usize {
self.bits
}
/// User Software Interrupt Pending
#[inline]
pub fn usoft(&self) -> bool {
self.bits.get_bit(0)
}
/// Supervisor Software Interrupt Pending
#[inline]
pub fn ssoft(&self) -> bool {
self.bits.get_bit(1)
}
/// User Timer Interrupt Pending
#[inline]
pub fn utimer(&self) -> bool {
self.bits.get_bit(4)
}
/// Supervisor Timer Interrupt Pending
#[inline]
pub fn stimer(&self) -> bool {
self.bits.get_bit(5)
}
/// User External Interrupt Pending
#[inline]
pub fn uext(&self) -> bool {
self.bits.get_bit(8)
}
/// Supervisor External Interrupt Pending
#[inline]
pub fn sext(&self) -> bool {
self.bits.get_bit(9)
}
}
read_csr_as!(Sip, 0x144, __read_sip);

View File

@ -1,4 +0,0 @@
//! sscratch register
read_csr_as_usize!(0x140, __read_sscratch);
write_csr_as_usize!(0x140, __write_sscratch);

View File

@ -1,140 +0,0 @@
//! sstatus register
use bit_field::BitField;
use core::mem::size_of;
pub use super::mstatus::FS;
/// Supervisor Status Register
#[derive(Clone, Copy, Debug)]
pub struct Sstatus {
bits: usize,
}
/// Supervisor Previous Privilege Mode
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum SPP {
Supervisor = 1,
User = 0,
}
impl Sstatus {
/// User Interrupt Enable
#[inline]
pub fn uie(&self) -> bool {
self.bits.get_bit(0)
}
/// Supervisor Interrupt Enable
#[inline]
pub fn sie(&self) -> bool {
self.bits.get_bit(1)
}
/// User Previous Interrupt Enable
#[inline]
pub fn upie(&self) -> bool {
self.bits.get_bit(4)
}
/// Supervisor Previous Interrupt Enable
#[inline]
pub fn spie(&self) -> bool {
self.bits.get_bit(5)
}
/// Supervisor Previous Privilege Mode
#[inline]
pub fn spp(&self) -> SPP {
match self.bits.get_bit(8) {
true => SPP::Supervisor,
false => SPP::User,
}
}
/// The status of the floating-point unit
#[inline]
pub fn fs(&self) -> FS {
match self.bits.get_bits(13..15) {
0 => FS::Off,
1 => FS::Initial,
2 => FS::Clean,
3 => FS::Dirty,
_ => unreachable!(),
}
}
/// The status of additional user-mode extensions
/// and associated state
#[inline]
pub fn xs(&self) -> FS {
match self.bits.get_bits(15..17) {
0 => FS::Off,
1 => FS::Initial,
2 => FS::Clean,
3 => FS::Dirty,
_ => unreachable!(),
}
}
/// Permit Supervisor User Memory access
#[inline]
pub fn sum(&self) -> bool {
self.bits.get_bit(18)
}
/// Make eXecutable Readable
#[inline]
pub fn mxr(&self) -> bool {
self.bits.get_bit(19)
}
/// Whether either the FS field or XS field
/// signals the presence of some dirty state
#[inline]
pub fn sd(&self) -> bool {
self.bits.get_bit(size_of::<usize>() * 8 - 1)
}
}
read_csr_as!(Sstatus, 0x100, __read_sstatus);
write_csr!(0x100, __write_sstatus);
set!(0x100, __set_sstatus);
clear!(0x100, __clear_sstatus);
set_clear_csr!(
/// User Interrupt Enable
, set_uie, clear_uie, 1 << 0);
set_clear_csr!(
/// Supervisor Interrupt Enable
, set_sie, clear_sie, 1 << 1);
set_csr!(
/// User Previous Interrupt Enable
, set_upie, 1 << 4);
set_csr!(
/// Supervisor Previous Interrupt Enable
, set_spie, 1 << 5);
set_clear_csr!(
/// Make eXecutable Readable
, set_mxr, clear_mxr, 1 << 19);
set_clear_csr!(
/// Permit Supervisor User Memory access
, set_sum, clear_sum, 1 << 18);
/// Supervisor Previous Privilege Mode
#[inline]
#[cfg(riscv)]
pub unsafe fn set_spp(spp: SPP) {
match spp {
SPP::Supervisor => _set(1 << 8),
SPP::User => _clear(1 << 8),
}
}
/// The status of the floating-point unit
#[inline]
#[cfg(riscv)]
pub unsafe fn set_fs(fs: FS) {
let mut value = _read();
value.set_bits(13..15, fs as usize);
_write(value);
}

View File

@ -1,3 +0,0 @@
//! stval register
read_csr_as_usize!(0x143, __read_stval);

View File

@ -1,40 +0,0 @@
//! stvec register
pub use crate::register::mtvec::TrapMode;
/// stvec register
#[derive(Clone, Copy, Debug)]
pub struct Stvec {
bits: usize,
}
impl Stvec {
/// Returns the contents of the register as raw bits
pub fn bits(&self) -> usize {
self.bits
}
/// Returns the trap-vector base-address
pub fn address(&self) -> usize {
self.bits - (self.bits & 0b11)
}
/// Returns the trap-vector mode
pub fn trap_mode(&self) -> TrapMode {
let mode = self.bits & 0b11;
match mode {
0 => TrapMode::Direct,
1 => TrapMode::Vectored,
_ => unimplemented!()
}
}
}
read_csr_as!(Stvec, 0x105, __read_stvec);
write_csr!(0x105, __write_stvec);
/// Writes the CSR
#[inline]
pub unsafe fn write(addr: usize, mode: TrapMode) {
_write(addr + mode as usize);
}

View File

@ -1,4 +0,0 @@
//! time register
read_csr_as_usize!(0xC01, __read_time);
read_composite_csr!(super::timeh::read(), read());

View File

@ -1,3 +0,0 @@
//! timeh register
read_csr_as_usize_rv32!(0xC81, __read_timeh);

View File

@ -1,17 +0,0 @@
//! ucause register
/// ucause register
#[derive(Clone, Copy, Debug)]
pub struct Ucause {
bits: usize,
}
impl Ucause {
/// Returns the contents of the register as raw bits
#[inline]
pub fn bits(&self) -> usize {
self.bits
}
}
read_csr_as!(Ucause, 0x042, __read_ucause);

View File

@ -1,4 +0,0 @@
//! uepc register
read_csr_as_usize!(0x041, __read_uepc);
write_csr_as_usize!(0x041, __write_uepc);

View File

@ -1,49 +0,0 @@
//! uie register
use bit_field::BitField;
/// uie register
#[derive(Clone, Copy, Debug)]
pub struct Uie {
bits: usize,
}
impl Uie {
/// Returns the contents of the register as raw bits
#[inline]
pub fn bits(&self) -> usize {
self.bits
}
/// User Software Interrupt Enable
#[inline]
pub fn usoft(&self) -> bool {
self.bits.get_bit(0)
}
/// User Timer Interrupt Enable
#[inline]
pub fn utimer(&self) -> bool {
self.bits.get_bit(4)
}
/// User External Interrupt Enable
#[inline]
pub fn uext(&self) -> bool {
self.bits.get_bit(8)
}
}
read_csr_as!(Uie, 0x004, __read_uie);
set!(0x004, __set_uie);
clear!(0x004, __clear_uie);
set_clear_csr!(
/// User Software Interrupt Enable
, set_usoft, clear_usoft, 1 << 0);
set_clear_csr!(
/// User Timer Interrupt Enable
, set_utimer, clear_utimer, 1 << 4);
set_clear_csr!(
/// User External Interrupt Enable
, set_uext, clear_uext, 1 << 8);

View File

@ -1,37 +0,0 @@
//! uip register
use bit_field::BitField;
/// uip register
#[derive(Clone, Copy, Debug)]
pub struct Uip {
bits: usize,
}
impl Uip {
/// Returns the contents of the register as raw bits
#[inline]
pub fn bits(&self) -> usize {
self.bits
}
/// User Software Interrupt Pending
#[inline]
pub fn usoft(&self) -> bool {
self.bits.get_bit(0)
}
/// User Timer Interrupt Pending
#[inline]
pub fn utimer(&self) -> bool {
self.bits.get_bit(4)
}
/// User External Interrupt Pending
#[inline]
pub fn uext(&self) -> bool {
self.bits.get_bit(8)
}
}
read_csr_as!(Uip, 0x044, __read_uip);

View File

@ -1,4 +0,0 @@
//! uscratch register
read_csr_as_usize!(0x040, __read_uscratch);
write_csr_as_usize!(0x040, __write_uscratch);

View File

@ -1,37 +0,0 @@
//! ustatus register
// TODO: Virtualization, Memory Privilege and Extension Context Fields
use bit_field::BitField;
/// ustatus register
#[derive(Clone, Copy, Debug)]
pub struct Ustatus {
bits: usize,
}
impl Ustatus {
/// User Interrupt Enable
#[inline]
pub fn uie(&self) -> bool {
self.bits.get_bit(0)
}
/// User Previous Interrupt Enable
#[inline]
pub fn upie(&self) -> bool {
self.bits.get_bit(4)
}
}
read_csr_as!(Ustatus, 0x000, __read_ustatus);
write_csr!(0x000, __write_ustatus);
set!(0x000, __set_ustatus);
clear!(0x000, __clear_ustatus);
set_clear_csr!(
/// User Interrupt Enable
, set_uie, clear_uie, 1 << 0);
set_csr!(
/// User Previous Interrupt Enable
, set_upie, 1 << 4);

View File

@ -1,3 +0,0 @@
//! utval register
read_csr_as_usize!(0x043, __read_utval);

View File

@ -1,40 +0,0 @@
//! stvec register
pub use crate::register::mtvec::TrapMode;
/// stvec register
#[derive(Clone, Copy, Debug)]
pub struct Utvec {
bits: usize,
}
impl Utvec {
/// Returns the contents of the register as raw bits
pub fn bits(&self) -> usize {
self.bits
}
/// Returns the trap-vector base-address
pub fn address(&self) -> usize {
self.bits - (self.bits & 0b11)
}
/// Returns the trap-vector mode
pub fn trap_mode(&self) -> TrapMode {
let mode = self.bits & 0b11;
match mode {
0 => TrapMode::Direct,
1 => TrapMode::Vectored,
_ => unimplemented!()
}
}
}
read_csr_as!(Utvec, 0x005, __read_utvec);
write_csr!(0x005, __write_utvec);
/// Writes the CSR
#[inline]
pub unsafe fn write(addr: usize, mode: TrapMode) {
_write(addr + mode as usize);
}

View File

@ -1,4 +1,3 @@
//! uscratch register
//! DCache Information register
read_csr_as_usize!(0xCC0, __read_vdci);
write_csr_as_usize!(0xCC0, __write_vdci);

View File

@ -1,4 +1,4 @@
//! uscratch register
//! Machine IRQ Mask register
read_csr_as_usize!(0xBC0, __read_vmim);
write_csr_as_usize!(0xBC0, __write_vmim);

View File

@ -1,4 +1,3 @@
//! uscratch register
//! Machine IRQ Pending register
read_csr_as_usize!(0xFC0, __read_vmip);
write_csr_as_usize!(0xFC0, __write_vmip);

View File

@ -1,4 +1,4 @@
//! uscratch register
//! Supervisor IRQ Mask register
read_csr_as_usize!(0x9C0, __read_vsim);
write_csr_as_usize!(0x9C0, __write_vsim);

View File

@ -1,4 +1,3 @@
//! uscratch register
//! Supervisor IRQ Pending register
read_csr_as_usize!(0xDC0, __read_vsip);
write_csr_as_usize!(0xDC0, __write_vsip);