use crate::isa::rvv::{LmulGroup, Sew, Vlmul};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
pub struct VRegIdx(u8);
impl VRegIdx {
#[inline(always)]
pub const fn new(val: u8) -> Self {
assert!(val < 32, "vector register index out of range");
Self(val)
}
#[inline(always)]
pub const fn as_u8(self) -> u8 {
self.0
}
#[inline(always)]
pub const fn as_usize(self) -> usize {
self.0 as usize
}
#[inline(always)]
pub const fn is_v0(self) -> bool {
self.0 == 0
}
#[inline(always)]
pub const fn is_aligned(self, group: LmulGroup) -> bool {
self.0.is_multiple_of(group.regs())
}
}
impl std::fmt::Display for VRegIdx {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "v{}", self.0)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Eew(Sew);
impl Eew {
#[inline(always)]
pub const fn new(sew: Sew) -> Self {
Self(sew)
}
#[inline(always)]
pub const fn sew(self) -> Sew {
self.0
}
#[inline(always)]
pub const fn bits(self) -> usize {
self.0.bits()
}
#[inline(always)]
pub const fn bytes(self) -> usize {
self.0.bytes()
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct ElemIdx(usize);
impl ElemIdx {
#[inline(always)]
pub const fn new(val: usize) -> Self {
Self(val)
}
#[inline(always)]
pub const fn as_usize(self) -> usize {
self.0
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Nf(u8);
impl Nf {
#[inline(always)]
pub const fn from_encoding(enc: u8) -> Self {
Self((enc & 0x7) + 1)
}
#[inline(always)]
pub const fn fields(self) -> u8 {
self.0
}
#[inline(always)]
pub const fn fields_usize(self) -> usize {
self.0 as usize
}
#[inline(always)]
pub const fn is_single(self) -> bool {
self.0 == 1
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Emul(u8);
impl Emul {
pub const fn compute(eew: Sew, sew: Sew, lmul: Vlmul) -> Self {
let (lnum, lden) = lmul.as_fraction();
let emul_num = eew.bits() * lnum;
let emul_den = sew.bits() * lden;
let emul = if emul_num >= emul_den { emul_num / emul_den } else { 1 };
Self(emul as u8)
}
#[inline(always)]
pub const fn regs(self) -> u8 {
self.0
}
}
#[cfg(test)]
#[allow(clippy::unwrap_used)]
mod tests {
use super::*;
#[test]
fn test_vregidx_range() {
let v0 = VRegIdx::new(0);
assert!(v0.is_v0());
assert_eq!(v0.as_u8(), 0);
let v31 = VRegIdx::new(31);
assert_eq!(v31.as_u8(), 31);
assert!(!v31.is_v0());
}
#[test]
#[should_panic(expected = "vector register index out of range")]
fn test_vregidx_out_of_range() {
let _ = VRegIdx::new(32);
}
#[test]
fn test_vregidx_alignment() {
let v0 = VRegIdx::new(0);
let v1 = VRegIdx::new(1);
let v4 = VRegIdx::new(4);
let group4 = Vlmul::M4.group_regs();
assert!(v0.is_aligned(group4));
assert!(!v1.is_aligned(group4));
assert!(v4.is_aligned(group4));
}
#[test]
fn test_nf() {
let nf = Nf::from_encoding(0);
assert_eq!(nf.fields(), 1);
assert!(nf.is_single());
let nf7 = Nf::from_encoding(7);
assert_eq!(nf7.fields(), 8);
assert!(!nf7.is_single());
}
}