Skip to content

Commit

Permalink
Reimplement register::mcause
Browse files Browse the repository at this point in the history
  • Loading branch information
FawazTirmizi committed Oct 14, 2022
1 parent ff568d4 commit 4cc9fe6
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 66 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]
- Disabled all CSR modules (`register::*`) (breaking change)
- Replaced CSR macros with new ones using `tock-registers`
- Reimplemeted CSR modules using new base functions:
- `mcause`

## [v0.9.0] - 2022-10-06

Expand Down
1 change: 0 additions & 1 deletion src/register/addresses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,6 @@ pub const CSR_MCOUNTINHIBIT: u16 = 0x320;
pub const CSR_MSCRATCH: u16 = 0x340;
#[allow(unused)]
pub const CSR_MEPC: u16 = 0x341;
#[allow(unused)]
pub const CSR_MCAUSE: u16 = 0x342;
#[allow(unused)]
pub const CSR_MTVAL: u16 = 0x343;
Expand Down
115 changes: 51 additions & 64 deletions src/register/mcause.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,75 @@
// Copyright (c) 2022 by Rivos Inc.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

//! mcause register
/// mcause register
#[derive(Clone, Copy, Debug)]
pub struct Mcause {
bits: usize,
ro_csr!(mcause, usize);

register_bitfields![usize,
#[cfg(target_pointer_width = "32")]
pub mcause [
cause OFFSET(0) NUMBITS(31) [],
is_interrupt OFFSET(31) NUMBITS(1) [],
],

#[cfg(target_pointer_width = "64")]
pub mcause [
cause OFFSET(0) NUMBITS(63) [],
is_interrupt OFFSET(63) NUMBITS(1) [],
],
];

/// Get the cause of the latest interrupt
#[inline]
pub fn cause() -> Trap {
let cause: usize = read_field(mcause::cause);
if is_interrupt() {
Trap::Interrupt(Interrupt::from(cause))
} else {
Trap::Exception(Exception::from(cause))
}
}

/// Returns `true` if the last trap was caused by an interrupt, otherwise
/// `false`.
#[inline]
pub fn is_interrupt() -> bool {
is_set(mcause::is_interrupt)
}

/// Trap Cause
/// Returns `true` if the last trap was caused by an exception, otherwise
/// `false`.
#[inline]
pub fn is_exception() -> bool {
!is_interrupt()
}

/// Enum wrapping both potential trap causes
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Trap {
Interrupt(Interrupt),
Exception(Exception),
}

/// Interrupt
// TODO: Maybe add a feature that changes these enums to use the actual values,
// and the conversion functions to use core::mem::transmute(). Assuming that
// the target platform doesn't use the reserved or custom interrupt lines this
// should be safe. This would only be worthwhile if the compiler doesn't already
// optimize the conversions out.
/// Interrupt causes
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Interrupt {
UserSoft,
SupervisorSoft,
MachineSoft,
UserTimer,
SupervisorTimer,
MachineTimer,
UserExternal,
SupervisorExternal,
MachineExternal,
Unknown,
}

/// Exception
/// Exception causes
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Exception {
InstructionMisaligned,
Expand All @@ -52,13 +93,10 @@ impl Interrupt {
#[inline]
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,
Expand Down Expand Up @@ -88,54 +126,3 @@ impl Exception {
}
}
}
impl Mcause {
/// Returns the contents of the register as raw bits
#[inline]
pub fn bits(&self) -> usize {
self.bits
}

/// Returns the code field
#[inline]
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);
2 changes: 1 addition & 1 deletion src/register/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ mod addresses;
//pub mod mtvec;

// Machine Trap Handling
//pub mod mcause;
pub mod mcause;
//pub mod mepc;
//pub mod mip;
//pub mod mscratch;
Expand Down

0 comments on commit 4cc9fe6

Please sign in to comment.