use crate::Simulator;
use crate::common::PhysAddr;
use crate::config::{Config, MemoryControllerKind};
use crate::isa::reg::RegIdx;
use crate::system::SystemState;
use crate::tests::support::mocks::memory::MockMemory;
use std::sync::Arc;
use std::sync::atomic::AtomicU64;
pub struct TestContext {
pub sim: Simulator,
}
impl Default for TestContext {
fn default() -> Self {
Self::new()
}
}
impl TestContext {
pub fn new() -> Self {
Self::new_with_config(&Config::default())
}
pub fn new_with_config(config: &Config) -> Self {
let _ = tracing_subscriber::fmt()
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
.with_test_writer()
.try_init();
let mut config = config.clone();
config.memory.controller = MemoryControllerKind::Simple;
config.memory.simple_latency = 1;
config.system.bus_latency = 0;
let exit_signal = Arc::new(AtomicU64::new(u64::MAX));
let state = SystemState::new(&config, "", exit_signal);
let sim = Simulator::new(state);
Self { sim }
}
pub fn cpu(&self) -> &SystemState {
&self.sim.state
}
pub fn cpu_mut(&mut self) -> &mut SystemState {
&mut self.sim.state
}
pub fn with_memory(mut self, size: usize, base: u64) -> Self {
let mem = MockMemory::new(size, base);
self.sim.state.bus.add_device(Box::new(mem));
self
}
pub fn load_program(mut self, addr: u64, instructions: &[u32]) -> Self {
for (i, inst) in instructions.iter().enumerate() {
let offset = addr + (i as u64) * 4;
self.sim.probe_mem_store(PhysAddr::new(offset), u64::from(*inst), 4);
}
self.sim.set_pc(0, addr);
self
}
pub fn set_reg(&mut self, reg: usize, val: u64) {
self.sim.state.harts[0].regs.write(RegIdx::new(reg as u8), val);
}
pub fn get_reg(&self, reg: usize) -> u64 {
self.sim.state.harts[0].regs.read(RegIdx::new(reg as u8))
}
pub fn run_until(&mut self, max_cycles: u64, done: impl Fn(&Self) -> bool) -> Option<u64> {
for _ in 0..max_cycles {
if done(self) {
return Some(self.sim.state.cycle);
}
if let Err(e) = self.sim.tick() {
eprintln!("CPU tick error: {}", e);
return None;
}
}
None
}
pub fn run(&mut self, cycles: u64) {
for _ in 0..cycles {
if let Err(e) = self.sim.tick() {
eprintln!("CPU tick error: {}", e);
break;
}
if self.sim.state.check_exit().is_some() {
break;
}
}
}
}