use ::cpu::op::Op;
#[cfg(feature = "rv32fd")]
use ::softfloat::Sf64;
use std::mem::size_of;
#[derive(Clone,Copy,Debug,Eq,PartialEq)]
pub enum CpuError {
MisalignedFetch,
IllegalFetch,
IllegalInstruction,
IllegalAccess,
MisalignedAccess,
Ecall,
Ebreak,
QuotaExceeded,
}
#[derive(Clone,Debug)]
#[cfg_attr(feature = "serialize", derive(Serialize,Deserialize))]
pub struct CpuState {
pub x: [u32; 32],
#[cfg(feature = "rv32fd")]
pub f: [Sf64; 32],
pub pc: u32,
pub fcsr: u32,
pub reservation: Option<u32>,
}
impl CpuState {
pub fn new(pc: u32) -> Self {
CpuState {
x: [0; 32],
#[cfg(feature = "rv32fd")]
f: [Sf64(0); 32],
pc,
fcsr: 0,
reservation: None,
}
}
}
pub enum MemoryAccess<'a, T: Copy + 'a> {
Load(&'a mut T),
Store(T),
Exec(&'a mut T),
}
pub trait Memory {
fn access<T: Copy>(&mut self, addr: u32, access: MemoryAccess<T>) -> bool;
}
impl Memory for [u8] {
fn access<T: Copy>(&mut self, addr: u32, access: MemoryAccess<T>) -> bool {
let addr = addr as usize;
let end = addr + size_of::<T>();
if let Some(slice) = self.get_mut(addr..end) {
let ptr = slice.as_mut_ptr() as *mut T;
match access {
MemoryAccess::Load(dest) | MemoryAccess::Exec(dest) => {
unsafe { *dest = *ptr };
},
MemoryAccess::Store(value) => {
unsafe { *ptr = value };
}
}
true
} else {
false
}
}
}
pub trait Clock {
fn read_cycle(&self) -> u64;
fn read_time(&self) -> u64;
fn read_instret(&self) -> u64;
fn progress(&mut self, op: &Op);
fn check_quota(&self) -> bool { true }
}
#[derive(Clone,Copy,Debug)]
#[cfg_attr(feature = "serialize", derive(Serialize,Deserialize))]
pub struct SimpleClock {
pub instret: u64,
}
impl SimpleClock {
pub fn new() -> Self {
SimpleClock { instret: 0 }
}
}
impl Clock for SimpleClock {
fn read_cycle(&self) -> u64 {
self.instret
}
fn read_time(&self) -> u64 {
self.instret
}
fn read_instret(&self) -> u64 {
self.instret
}
fn progress(&mut self, _op: &Op) {
self.instret = self.instret.wrapping_add(1);
}
}