feat: implement virtual clock timing architecture (Phases 5-8)

Introduces a VirtualClock-based timing system replacing wall-clock
Instant-based timing for hardware-accurate simulation.

New modules:
- virtual_clock.rs: Shared virtual time source with condvar sync
- real_time_governor.rs: Thread that advances virtual time
- component_timing.rs: Per-component timing constraints

Key changes:
- Component trait: added update_at_time(), timing(), set_virtual_clock_optional()
- All Intel 400x components migrated to virtual-time-aware operation
- ConfigurableSystem: start() returns Result, spawns governor thread
- GUI: timing controls (speed slider, mode selector, step button)
- Console: speed/mode/step/time commands
- Backward compatible: legacy fallback for components without VirtualClock

Reviewed-by: code review found 2 warnings (clock resume() dead code,
reset() safety docs) — both fixed.
This commit is contained in:
Jan-Peter von Hunnius 2026-05-14 21:00:22 +02:00
parent add7ace674
commit 08f53d68fe
28 changed files with 7186 additions and 270 deletions

View file

@ -17,6 +17,7 @@ mod intel_400x_tests;
// Common test utilities and helpers
pub mod test_utils {
use std::sync::Arc;
use std::time::{Duration, Instant};
/// Create a deterministic time source for testing
@ -34,6 +35,57 @@ pub mod test_utils {
std::thread::sleep(duration);
}
/// Create a VirtualClock in MaxSpeed mode for fast deterministic tests.
///
/// The clock starts in stopped state. Call `clock.start()` after spawning
/// the governor thread.
///
/// # Parameters
/// - `tick_size_ns`: Virtual time advance per tick (default: 333ns for 750 kHz)
pub fn create_maxspeed_clock(tick_size_ns: u64) -> Arc<rusty_emu::virtual_clock::VirtualClock> {
let clock = Arc::new(rusty_emu::virtual_clock::VirtualClock::new(
Duration::from_nanos(tick_size_ns),
));
clock.set_mode(rusty_emu::virtual_clock::SimulationMode::MaxSpeed);
clock
}
/// Create a VirtualClock in SingleStep mode for precise state verification.
///
/// Each call to `clock.trigger_step()` advances virtual time by one tick.
pub fn create_singlestep_clock(tick_size_ns: u64) -> Arc<rusty_emu::virtual_clock::VirtualClock> {
let clock = Arc::new(rusty_emu::virtual_clock::VirtualClock::new(
Duration::from_nanos(tick_size_ns),
));
clock.set_mode(rusty_emu::virtual_clock::SimulationMode::SingleStep);
clock
}
/// Spawn a RealTimeGovernor thread for the given clock.
///
/// Returns a JoinHandle that can be used to wait for the governor to exit.
/// The governor will exit when `clock.stop()` is called.
pub fn spawn_governor(
clock: Arc<rusty_emu::virtual_clock::VirtualClock>,
) -> std::thread::JoinHandle<()> {
std::thread::spawn(move || {
let governor = rusty_emu::real_time_governor::RealTimeGovernor::with_defaults(clock);
governor.run();
})
}
/// Stop the virtual clock and wait for the governor thread to finish.
///
/// This ensures clean shutdown of the governor thread before the test ends.
pub fn stop_governor(
clock: &Arc<rusty_emu::virtual_clock::VirtualClock>,
handle: std::thread::JoinHandle<()>,
) {
clock.stop();
// Give the governor thread a moment to exit cleanly
let _ = handle.join();
}
/// Verify that a component implements all required traits
pub fn verify_intel400x_traits<C>(component: &C)
where