use crate::v::private::SupportedElenVlen;
use crate::{Csrs, CustomErrorPlaceholder};
use ab_riscv_primitives::prelude::*;
use core::fmt;
use core::ops::{Deref, DerefMut};
#[derive(Debug, Clone, Copy)]
#[repr(align(128))]
pub struct VectorRegisterFile<const VLENB: usize>([[u8; VLENB]; 32]);
impl<const VLENB: usize> const Default for VectorRegisterFile<VLENB> {
#[inline(always)]
fn default() -> Self {
Self([[0; VLENB]; 32])
}
}
impl<const VLENB: usize> const Deref for VectorRegisterFile<VLENB> {
type Target = [[u8; VLENB]; 32];
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<const VLENB: usize> const DerefMut for VectorRegisterFile<VLENB> {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
pub trait VectorRegistersBase {
const ELEN: u32;
const VLEN: u32;
const VLENB: u32 = Self::VLEN / u8::BITS;
}
pub trait VectorRegisters<CustomError = CustomErrorPlaceholder>
where
Self: VectorRegistersBase + SupportedElenVlen<{ Self::ELEN }, { Self::VLEN }>,
{
fn read_vreg(&self) -> &VectorRegisterFile<{ Self::VLENB as usize }>;
fn write_vreg(&mut self) -> &mut VectorRegisterFile<{ Self::VLENB as usize }>;
fn vtype(&self) -> Option<Vtype<{ Self::ELEN }, { Self::VLEN }>>;
fn set_vtype(&mut self, vtype: Option<Vtype<{ Self::ELEN }, { Self::VLEN }>>);
fn vl(&self) -> u32;
fn set_vl(&mut self, vl: u32);
fn vector_instructions_allowed(&self) -> bool;
fn mark_vs_dirty(&mut self);
#[inline(always)]
fn compute_vl(&self, avl: u32, vlmax: u32) -> u32 {
avl.min(vlmax)
}
#[inline(always)]
fn vlmax_for_vtype(&self, vtype: Vtype<{ Self::ELEN }, { Self::VLEN }>) -> u32 {
vtype
.vlmul()
.vlmax(Self::VLEN, u32::from(vtype.vsew().bits()))
}
}
pub trait VectorRegistersExt<Reg, CustomError = CustomErrorPlaceholder>
where
Self: Csrs<Reg, CustomError> + VectorRegisters<CustomError>,
[(); Self::ELEN as usize]:,
[(); Self::VLEN as usize]:,
Reg: Register,
CustomError: fmt::Debug,
{
fn initialize_vector_state(&mut self) {
self.set_vtype(None);
self.set_vl(0);
self.set_vstart(0);
self.set_vxrm(Vxrm::Rnu);
self.set_vxsat(false);
}
#[inline(always)]
fn vstart(&self) -> u16 {
let raw = self
.read_csr(VCsr::Vstart as u16)
.unwrap_or_default()
.as_u64();
raw as u16
}
#[inline(always)]
fn set_vstart(&mut self, vstart: u16) {
self.write_csr(VCsr::Vstart as u16, Reg::Type::from(vstart))
.expect("Implementation didn't initialize `vstart` CSR")
}
#[inline(always)]
fn reset_vstart(&mut self) {
self.set_vstart(0);
}
#[inline(always)]
fn vxrm(&self) -> Vxrm {
let raw = self
.read_csr(VCsr::Vxrm as u16)
.unwrap_or_default()
.as_u64();
Vxrm::from_bits(raw as u8)
}
#[inline(always)]
fn set_vxrm(&mut self, vxrm: Vxrm) {
let masked = Reg::Type::from(vxrm.to_bits());
self.write_csr(VCsr::Vxrm as u16, masked)
.expect("Implementation didn't initialize `vxrm` CSR");
let old_vcsr = self.read_csr(VCsr::Vcsr as u16).unwrap_or_default();
let new_vcsr = (old_vcsr & !Reg::Type::from(0b110u8)) | (masked << 1);
self.write_csr(VCsr::Vcsr as u16, new_vcsr)
.expect("Implementation didn't initialize `vcsr` CSR");
}
#[inline(always)]
fn vxsat(&self) -> bool {
let raw = self
.read_csr(VCsr::Vxsat as u16)
.unwrap_or_default()
.as_u64();
(raw & 1) != 0
}
#[inline(always)]
fn set_vxsat(&mut self, vxsat: bool) {
let masked = Reg::Type::from(u8::from(vxsat));
self.write_csr(VCsr::Vxsat as u16, masked)
.expect("Implementation didn't initialize `vxsat` CSR");
let old_vcsr = self.read_csr(VCsr::Vcsr as u16).unwrap_or_default();
let new_vcsr = (old_vcsr & !Reg::Type::from(1u8)) | masked;
self.write_csr(VCsr::Vcsr as u16, new_vcsr)
.expect("Implementation didn't initialize `vcsr` CSR");
}
}