eeric 0.0.52

An easily embeddable RV64I core with MFDV extensions
Documentation
use crate::{prelude::Snapshotable, rv_core::vector_engine::Vlen};

use super::aliases::csr::VLENB;

#[derive(Clone, PartialEq)]
#[cfg_attr(debug_assertions, derive(Debug))]
pub enum CsrPrivilege {
    ReadOnly,
    ReadWrite,
}

#[derive(Clone, PartialEq)]
#[cfg_attr(debug_assertions, derive(Debug))]
pub struct CsrRegister {
    value: u64,
    pub privilege: CsrPrivilege,
}

impl CsrRegister {
    pub fn read(&self) -> u64 {
        self.value
    }

    pub fn write(&mut self, value: u64) -> Result<(), String> {
        if self.privilege == CsrPrivilege::ReadOnly {
            return Err("Cannot write to read-only register".to_owned());
        }

        unsafe {
            self.set(value);
        }

        Ok(())
    }

    pub unsafe fn set(&mut self, value: u64) {
        self.value = value;
    }
}

#[derive(Clone, PartialEq)]
#[cfg_attr(debug_assertions, derive(Debug))]
pub struct CsrRegisters([CsrRegister; 4096]);

impl Snapshotable for CsrRegisters {
    type Snapshot = [CsrRegister; 4096];

    fn snapshot(&self) -> Self::Snapshot {
        self.0.clone()
    }
}

impl CsrRegisters {
    pub fn new(vlen: &Vlen) -> Self {
        let mut regs = Self::default();

        unsafe { regs[VLENB].set(vlen.byte_length() as u64) }

        regs
    }
}

impl Default for CsrRegisters {
    fn default() -> Self {
        let mut index = 0;
        Self([0; 4096].map(|_| {
            let privilege = if ((index >> 10) & 0b11) == 0b11 {
                CsrPrivilege::ReadOnly
            } else {
                CsrPrivilege::ReadWrite
            };
            let register = CsrRegister {
                value: 0,
                privilege,
            };

            index += 1;

            register
        }))
    }
}

impl std::ops::Index<usize> for CsrRegisters {
    type Output = CsrRegister;

    fn index(&self, index: usize) -> &Self::Output {
        &self.0[index]
    }
}

impl std::ops::IndexMut<usize> for CsrRegisters {
    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
        &mut self.0[index]
    }
}