Skip to content

Commit

Permalink
Merge branch 'master' into riscv-pac
Browse files Browse the repository at this point in the history
  • Loading branch information
romancardenas committed May 30, 2024
2 parents 6c75aa0 + 7291ac2 commit 7762939
Show file tree
Hide file tree
Showing 10 changed files with 218 additions and 8 deletions.
4 changes: 4 additions & 0 deletions riscv-peripheral/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

- `PLIC` now expects interrupt enums to implement the `riscv_pac::ExternalInterruptNumber` trait.

### Fixed

- `clippy` fixes

## [v0.1.0] - 2024-02-15

### Added
Expand Down
2 changes: 1 addition & 1 deletion riscv-peripheral/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! ## Features
//!
//! - `aclint-hal-async`: enables the [`hal_async::delay::DelayNs`] implementation for the ACLINT peripheral.
//! This feature relies on external functions that must be provided by the user. See [`hal_async::aclint`] for more information.
//! This feature relies on external functions that must be provided by the user. See [`hal_async::aclint`] for more information.

#![deny(missing_docs)]
#![no_std]
Expand Down
2 changes: 2 additions & 0 deletions riscv-rt/macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -483,12 +483,14 @@ fn vectored_interrupt_trap(arch: RiscvArch) -> TokenStream {
core::arch::global_asm!(
".section .trap, \"ax\"
.align 4
.global _start_DefaultHandler_trap
_start_DefaultHandler_trap:
addi sp, sp, -{TRAP_SIZE} * {width} // allocate space for trap frame
{store_start} // store trap partially (only register a0)
la a0, DefaultHandler // load interrupt handler address into a0
.align 4
.global _continue_interrupt_trap
_continue_interrupt_trap:
{store_continue} // store trap partially (all registers except a0)
Expand Down
1 change: 1 addition & 0 deletions riscv-semihosting/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
### Changed

- Made `cfg` variable selection more robust for custom targets
- Fixed debug::exit() on riscv64 QEMU simulation

## [v0.1.0] - 2023-01-18

Expand Down
4 changes: 4 additions & 0 deletions riscv-semihosting/src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ pub fn exit(status: ExitStatus) {
pub fn report_exception(reason: Exception) {
let code = reason as usize;
unsafe {
#[cfg(target_arch = "riscv64")]
syscall!(REPORT_EXCEPTION, code, 0);

#[cfg(not(target_arch = "riscv64"))]
syscall1!(REPORT_EXCEPTION, code);
}
}
3 changes: 3 additions & 0 deletions riscv/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Add `Mstatus::update_*` helpers to manipulate Mstatus values without touching
the CSR
- Export `riscv::register::macros` module macros for external use
- Add `riscv::register::mcountinhibit` module for `mcountinhibit` CSR
- Add `Mcounteren` in-memory update functions

### Changed

Expand All @@ -26,6 +28,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Fixed

- Fixed `sip::set_ssoft` and `sip::clear_ssoft` using wrong address
- Fixed assignment in `mstatus` unit tests.

## [v0.11.1] - 2024-02-15

Expand Down
4 changes: 2 additions & 2 deletions riscv/src/interrupt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ pub mod machine {
/// - Do not call this function inside a critical section.
/// - This method is assumed to be called within an interrupt handler.
/// - Make sure to clear the interrupt flag that caused the interrupt before calling
/// this method. Otherwise, the interrupt will be re-triggered before executing `f`.
/// this method. Otherwise, the interrupt will be re-triggered before executing `f`.
#[inline]
pub unsafe fn nested<F, R>(f: F) -> R
where
Expand Down Expand Up @@ -152,7 +152,7 @@ pub mod supervisor {
/// - Do not call this function inside a critical section.
/// - This method is assumed to be called within an interrupt handler.
/// - Make sure to clear the interrupt flag that caused the interrupt before calling
/// this method. Otherwise, the interrupt will be re-triggered before executing `f`.
/// this method. Otherwise, the interrupt will be re-triggered before executing `f`.
#[inline]
pub unsafe fn nested<F, R>(f: F) -> R
where
Expand Down
1 change: 1 addition & 0 deletions riscv/src/register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ mod pmpaddrx;
pub use self::pmpaddrx::*;

// Machine Counter/Timers
pub mod mcountinhibit;
pub mod mcycle;
pub mod mcycleh;
mod mhpmcounterx;
Expand Down
89 changes: 84 additions & 5 deletions riscv/src/register/mcounteren.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! mcounteren register

use crate::bits::{bf_extract, bf_insert};

/// mcounteren register
#[derive(Clone, Copy, Debug)]
pub struct Mcounteren {
Expand All @@ -10,31 +12,64 @@ impl Mcounteren {
/// Supervisor "cycle\[h\]" Enable
#[inline]
pub fn cy(&self) -> bool {
self.bits & (1 << 0) != 0
bf_extract(self.bits, 0, 1) != 0
}

/// Sets whether to enable the "cycle\[h\]" counter.
///
/// Only updates the in-memory value, does not modify the `mcounteren` register.
#[inline]
pub fn set_cy(&mut self, cy: bool) {
self.bits = bf_insert(self.bits, 0, 1, cy as usize);
}

/// Supervisor "time\[h\]" Enable
#[inline]
pub fn tm(&self) -> bool {
self.bits & (1 << 1) != 0
bf_extract(self.bits, 1, 1) != 0
}

/// Sets whether to enable "time\[h\]".
///
/// Only updates the in-memory value, does not modify the `mcounteren` register.
#[inline]
pub fn set_tm(&mut self, tm: bool) {
self.bits = bf_insert(self.bits, 1, 1, tm as usize);
}

/// Supervisor "instret\[h\]" Enable
#[inline]
pub fn ir(&self) -> bool {
self.bits & (1 << 2) != 0
bf_extract(self.bits, 2, 1) != 0
}

/// Sets whether to enable the "instret\[h\]" counter.
///
/// Only updates the in-memory value, does not modify the `mcounteren` register.
#[inline]
pub fn set_ir(&mut self, ir: bool) {
self.bits = bf_insert(self.bits, 2, 1, ir as usize);
}

/// Supervisor "hpm\[x\]" Enable (bits 3-31)
#[inline]
pub fn hpm(&self, index: usize) -> bool {
assert!((3..32).contains(&index));
self.bits & (1 << index) != 0
bf_extract(self.bits, index, 1) != 0
}

/// Sets whether to enable the "hpm\[X\]" counter.
///
/// Only updates the in-memory value, does not modify the `mcounteren` register.
#[inline]
pub fn set_hpm(&mut self, index: usize, hpm: bool) {
assert!((3..32).contains(&index));
self.bits = bf_insert(self.bits, index, 1, hpm as usize);
}
}

read_csr_as!(Mcounteren, 0x306);
write_csr!(0x306);
write_csr_as!(Mcounteren, 0x306);
set!(0x306);
clear!(0x306);

Expand All @@ -61,3 +96,47 @@ pub unsafe fn clear_hpm(index: usize) {
assert!((3..32).contains(&index));
_clear(1 << index);
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_mcounteren() {
let mut m = Mcounteren { bits: 0 };

assert!(!m.cy());

m.set_cy(true);
assert!(m.cy());

m.set_cy(false);
assert!(!m.cy());

assert!(!m.tm());

m.set_tm(true);
assert!(m.tm());

m.set_tm(false);
assert!(!m.tm());

assert!(!m.ir());

m.set_ir(true);
assert!(m.ir());

m.set_ir(false);
assert!(!m.ir());

(3..32).for_each(|i| {
assert!(!m.hpm(i));

m.set_hpm(i, true);
assert!(m.hpm(i));

m.set_hpm(i, false);
assert!(!m.hpm(i));
});
}
}
116 changes: 116 additions & 0 deletions riscv/src/register/mcountinhibit.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
//! `mcountinhibit` register

use crate::bits::{bf_extract, bf_insert};

/// `mcountinhibit` register
#[derive(Clone, Copy, Debug)]
pub struct Mcountinhibit {
bits: usize,
}

impl Mcountinhibit {
/// Machine "cycle\[h\]" Disable
#[inline]
pub fn cy(&self) -> bool {
bf_extract(self.bits, 0, 1) != 0
}

/// Sets whether to inhibit the "cycle\[h\]" counter.
///
/// Only updates the in-memory value, does not modify the `mcountinhibit` register.
#[inline]
pub fn set_cy(&mut self, cy: bool) {
self.bits = bf_insert(self.bits, 0, 1, cy as usize);
}

/// Machine "instret\[h\]" Disable
#[inline]
pub fn ir(&self) -> bool {
bf_extract(self.bits, 2, 1) != 0
}

/// Sets whether to inhibit the "instret\[h\]" counter.
///
/// Only updates the in-memory value, does not modify the `mcountinhibit` register.
#[inline]
pub fn set_ir(&mut self, ir: bool) {
self.bits = bf_insert(self.bits, 2, 1, ir as usize);
}

/// Machine "hpm\[x\]" Disable (bits 3-31)
#[inline]
pub fn hpm(&self, index: usize) -> bool {
assert!((3..32).contains(&index));
bf_extract(self.bits, index, 1) != 0
}

/// Sets whether to inhibit the "hpm\[X\]" counter.
///
/// Only updates the in-memory value, does not modify the `mcountinhibit` register.
#[inline]
pub fn set_hpm(&mut self, index: usize, hpm: bool) {
assert!((3..32).contains(&index));
self.bits = bf_insert(self.bits, index, 1, hpm as usize);
}
}

read_csr_as!(Mcountinhibit, 0x320);
write_csr_as!(Mcountinhibit, 0x320);
set!(0x320);
clear!(0x320);

set_clear_csr!(
/// Machine cycle Disable
, set_cy, clear_cy, 1 << 0);

set_clear_csr!(
/// Machine instret Disable
, set_ir, clear_ir, 1 << 2);

#[inline]
pub unsafe fn set_hpm(index: usize) {
assert!((3..32).contains(&index));
_set(1 << index);
}

#[inline]
pub unsafe fn clear_hpm(index: usize) {
assert!((3..32).contains(&index));
_clear(1 << index);
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_mcountinhibit() {
let mut m = Mcountinhibit { bits: 0 };

assert!(!m.cy());

m.set_cy(true);
assert!(m.cy());

m.set_cy(false);
assert!(!m.cy());

assert!(!m.ir());

m.set_ir(true);
assert!(m.ir());

m.set_ir(false);
assert!(!m.ir());

(3..32).for_each(|i| {
assert!(!m.hpm(i));

m.set_hpm(i, true);
assert!(m.hpm(i));

m.set_hpm(i, false);
assert!(!m.hpm(i));
});
}
}

0 comments on commit 7762939

Please sign in to comment.