use std::time::{Duration, Instant};
use super::cpu::Cpu;
use super::machine::Machine;
pub struct TimedRunner {
mhz: f64,
quantum_cycles: u64,
prev_cycle: u64,
prev_time: Instant,
}
impl TimedRunner {
pub fn new() -> TimedRunner {
TimedRunner {
mhz: 0.0,
quantum_cycles: 0,
prev_cycle: 0,
prev_time: Instant::now(),
}
}
pub fn set_mhz(&mut self, cpu: &Cpu, mhz: f64, quantum_cycles: u64) {
self.mhz = mhz;
self.quantum_cycles = quantum_cycles;
self.prev_cycle = cpu.cycle_count();
self.prev_time = Instant::now();
}
pub fn execute(&mut self, cpu: &mut Cpu, sys: &mut dyn Machine) {
if cpu.is_halted() {
return;
}
if self.mhz != 0.0 {
let cycles_elapsed = cpu.cycle_count() - self.prev_cycle;
if cycles_elapsed > self.quantum_cycles {
let now = Instant::now();
let target_time = self.prev_time + Duration::from_nanos((cycles_elapsed as f64 * 1000.0 / self.mhz) as u64);
if now < target_time {
std::thread::sleep(target_time - now);
}
self.prev_cycle = cpu.cycle_count();
self.prev_time = target_time;
}
}
cpu.execute_instruction(sys);
}
}