use super::free_list::PhysRegister;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
pub struct PhysReg(pub u16);
impl PhysRegister for PhysReg {
#[inline]
fn is_zero(self) -> bool {
self.0 == 0
}
#[inline]
fn from_index(idx: u16) -> Self {
Self(idx)
}
}
#[derive(Debug)]
pub struct PhysRegFile {
values: Vec<u64>,
ready: Vec<bool>,
}
impl PhysRegFile {
pub fn new(total: usize) -> Self {
let mut ready = vec![false; total];
if total > 0 {
ready[0] = true; }
Self { values: vec![0u64; total], ready }
}
#[inline]
pub fn write(&mut self, p: PhysReg, val: u64) {
let idx = p.0 as usize;
if idx == 0 {
return; }
if idx < self.values.len() {
self.values[idx] = val;
self.ready[idx] = true;
}
}
#[inline]
pub fn read(&self, p: PhysReg) -> u64 {
let idx = p.0 as usize;
if idx < self.values.len() { self.values[idx] } else { 0 }
}
#[inline]
pub fn is_ready(&self, p: PhysReg) -> bool {
let idx = p.0 as usize;
if idx < self.ready.len() { self.ready[idx] } else { false }
}
pub fn mark_arch_ready(&mut self, num_arch: usize) {
let limit = num_arch.min(self.ready.len());
for i in 0..limit {
self.ready[i] = true;
}
}
#[inline]
pub fn allocate(&mut self, p: PhysReg) {
let idx = p.0 as usize;
if idx == 0 {
return; }
if idx < self.ready.len() {
self.ready[idx] = false;
}
}
pub const fn capacity(&self) -> usize {
self.values.len()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_phys_reg_zero_always_ready() {
let prf = PhysRegFile::new(64);
assert!(prf.is_ready(PhysReg(0)));
assert_eq!(prf.read(PhysReg(0)), 0);
}
#[test]
fn test_write_read_lifecycle() {
let mut prf = PhysRegFile::new(64);
let p = PhysReg(5);
assert!(!prf.is_ready(p));
prf.write(p, 42);
assert!(prf.is_ready(p));
assert_eq!(prf.read(p), 42);
}
#[test]
fn test_allocate_marks_not_ready() {
let mut prf = PhysRegFile::new(64);
let p = PhysReg(10);
prf.write(p, 99);
assert!(prf.is_ready(p));
prf.allocate(p);
assert!(!prf.is_ready(p));
}
#[test]
fn test_allocate_zero_noop() {
let mut prf = PhysRegFile::new(64);
prf.allocate(PhysReg(0));
assert!(prf.is_ready(PhysReg(0)));
}
#[test]
fn test_write_zero_noop() {
let mut prf = PhysRegFile::new(64);
prf.write(PhysReg(0), 999);
assert_eq!(prf.read(PhysReg(0)), 0);
}
}