Skip to content

Commit

Permalink
Merge pull request #255 from rmsyn/riscv/mvendorid-csr-macro
Browse files Browse the repository at this point in the history
riscv: define mvendorid CSR with macro helpers
  • Loading branch information
romancardenas authored Jan 15, 2025
2 parents 1da169b + 4a0bab7 commit b391a48
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 22 deletions.
1 change: 1 addition & 0 deletions riscv/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Use CSR helper macros to define `mstatus` register
- Use CSR helper macros to define `mstatush` register
- Use CSR helper macros to define `mtvec` register
- Use CSR helper macros to define `mtvendorid` register

## [v0.12.1] - 2024-10-20

Expand Down
110 changes: 88 additions & 22 deletions riscv/src/register/mvendorid.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,100 @@
//! mvendorid register
use core::num::NonZeroUsize;
read_only_csr! {
/// `mvendorid` register
Mvendorid: 0xF11,
mask: 0xffff_ffff,
sentinel: 0,
}

read_only_csr_field! {
Mvendorid,
/// Represents the number of continuation bytes (`0x7f`) in the JEDEC manufacturer ID.
bank: [7:31],
}

/// mvendorid register
#[derive(Clone, Copy, Debug)]
pub struct Mvendorid {
bits: NonZeroUsize,
read_only_csr_field! {
Mvendorid,
/// Represents the final offset field in the JEDEC manufacturer ID.
///
/// # Note
///
/// The encoded value returned by `offset` does not include the odd parity bit (`0x80`).
offset: [0:6],
}

impl Mvendorid {
/// Returns the contents of the register as raw bits
#[inline]
pub fn bits(&self) -> usize {
self.bits.get()
}
/// Represents the JEDEC manufacture continuation byte.
pub const CONTINUATION: u8 = 0x7f;

/// Returns the JEDEC manufacturer ID
#[inline]
pub fn jedec_manufacturer(&self) -> usize {
self.bits() >> 7
/// Gets the decoded JEDEC manufacturer ID from the `mvendorid` value.
///
/// # Note
///
/// This function returns an iterator over the decoded bytes.
///
/// An iterator is needed because the encoding can theoretically return a max count (`0x1ff_ffff`) of continuation bytes (`0x7f`).
///
/// The final byte in the iterator is the `offset`, including the odd parity bit (set only if even).
pub fn jedec_manufacturer(&self) -> impl Iterator<Item = u8> {
const DONE: usize = usize::MAX;

let mut bank = self.bank();
let offset = self.offset();

core::iter::from_fn(move || match bank {
DONE => None,
0 => {
bank = DONE;
let parity = ((1 - (offset.count_ones() % 2)) << 7) as usize;
Some((parity | offset) as u8)
}
_ => {
bank -= 1;
Some(Self::CONTINUATION)
}
})
}
}

read_csr!(0xF11);
#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_mvendorid() {
(0..u32::BITS)
.map(|r| ((1u64 << r) - 1) as usize)
.for_each(|raw| {
let exp_bank = raw >> 7;
let exp_offset = raw & (Mvendorid::CONTINUATION as usize);
let exp_parity = ((1 - (exp_offset.count_ones() % 2)) << 7) as u8;
let exp_mvendorid = Mvendorid::from_bits(raw);

/// 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 })
assert_eq!(exp_mvendorid.bank(), exp_bank);
assert_eq!(exp_mvendorid.offset(), exp_offset);

let mut jedec_iter = exp_mvendorid.jedec_manufacturer();
(0..exp_bank)
.for_each(|_| assert_eq!(jedec_iter.next(), Some(Mvendorid::CONTINUATION)));
assert_eq!(jedec_iter.next(), Some(exp_parity | (exp_offset as u8)));
assert_eq!(jedec_iter.next(), None);
});

// ISA example used as a concrete test vector.

let exp_bank = 0xc;
let exp_offset = 0x0a;
let exp_decoded_offset = 0x8a;
let raw_mvendorid = 0x60a;
let exp_mvendorid = Mvendorid::from_bits(raw_mvendorid);

assert_eq!(exp_mvendorid.bank(), exp_bank);
assert_eq!(exp_mvendorid.offset(), exp_offset);

let mut jedec_iter = exp_mvendorid.jedec_manufacturer();
(0..exp_bank).for_each(|_| assert_eq!(jedec_iter.next(), Some(Mvendorid::CONTINUATION)));
assert_eq!(jedec_iter.next(), Some(exp_decoded_offset));
assert_eq!(jedec_iter.next(), None);
}
}

0 comments on commit b391a48

Please sign in to comment.