Skip to content

Instantly share code, notes, and snippets.

@dkhayes117
Created August 15, 2021 18:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dkhayes117/926f26687e9821820b830af46fb9e797 to your computer and use it in GitHub Desktop.
Save dkhayes117/926f26687e9821820b830af46fb9e797 to your computer and use it in GitHub Desktop.
PMP Address APIs
/// All possible errors for this crate
#[derive(Debug)]
pub enum Error<E> {
MisalignedAddress,
IncorrectGranularity
}
pub trait PmpAddressEncoding<E> {
fn into_range_encoding(self) -> Result<Pmprange, Error<E>>;
}
/// Determines the granularity of a given pmp address value
pub fn get_granularity(value: usize) -> usize {
use core::mem;
assert!(value > 0);
let mut index = 0;
for i in 0..mem::size_of::<usize>() {
if ((value >> i) & 0x1) == 1 {
index = i;
break
}
}
1 << (index + 3)
}
/// addr is the memory address that forms the top of the memory range
///
/// Must be 4-byte aligned
pub fn encode_as_tor<E>(addr: usize) -> Result<usize, Error<E>> {
if addr % 4 > 0 {
return Err(Error::MisalignedAddress);
}
Ok(addr >> 2)
}
/// base is the starting address for the range, base + size is the top of that range
///
/// Must be 4-byte aligned
pub fn encode_as_napot<E>(base: usize, size: usize) -> Result<usize, Error<E>> {
if (base % 4 > 0) | (size % 4 > 0) {
return Err(Error::MisalignedAddress);
}
let napot_size = (size / 2) - 1;
Ok((base + napot_size) >> 2)
}
/// Defines a 4-byte address range, and must be 4 byte aligned
///
/// Must be 4-byte aligned
pub fn encode_as_na4<E>(addr: usize) -> Result<usize, Error<E>> {
let value = addr >> 2;
if get_granularity(value) > 4 {
return Err(Error::IncorrectGranularity);
}
Ok(value)
}
/// Testing code for PmpAddr1
pub struct Pmprange {
/// The base address of the configuration
base: usize,
/// Size of the range
size:usize
}
pub struct Pmpaddr {
/// Holds the raw contents of a Pmpaddr Register
bits:usize
}
pub mod pmpaddr0{
use super::{Pmpaddr,Pmprange, Error};
use register::PmpAddressEncoding;
read_csr_as!(Pmpaddr, 0x3B0, __read_pmpaddr0);
write_csr_as_usize!(0x3B0, __write_pmpaddr0);
impl <E> PmpAddressEncoding<E> for Pmpaddr {
fn into_range_encoding(self) -> Result<Pmprange, Error<E>> {
if self.bits == 0 {Err(Error::MisalignedAddress)}
Ok(Pmprange{
base: self.bits << 2,
size: self.bits << 2
})
}
}
}
//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);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment