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

@ -0,0 +1,117 @@
# Phase 8: Speed/Step Controls for GUI and Console
## Overview
Add simulation speed, mode, and step controls to both the egui-based GUI and the ratatui-based console interface. These controls leverage the existing `VirtualClock` and `RealTimeGovernor` APIs.
## Files to Modify
1. **`src/gui/state.rs`** — Add `TimingState` struct to `GuiState` for virtual time display data
2. **`src/gui/components.rs`** — Add `TimingControls` component (speed slider, mode selector, step button, time display)
3. **`src/gui/mod.rs`** — Integrate `TimingControls` into the main render loop
4. **`src/gui/console.rs`** — Add console commands: `speed`, `mode`, `step`, `time`
## Detailed Design
### 1. GUI State (`src/gui/state.rs`)
Add a `TimingState` struct to `GuiState`:
```rust
pub struct TimingState {
/// Current virtual time in nanoseconds
pub virtual_time_ns: u64,
/// Total ticks elapsed
pub tick_count: u64,
/// Current speed multiplier (from VirtualClock)
pub target_speed: f64,
/// Actual measured speed (from RealTimeGovernor snapshots)
pub actual_speed: f64,
/// Current simulation mode: "RealTime", "MaxSpeed", "SingleStep"
pub mode: String,
/// Whether a step is pending (SingleStep mode)
pub step_pending: bool,
}
```
The `update_from_system()` method will be extended to:
- Access `ConfigurableSystem::get_virtual_clock()` → `Arc<VirtualClock>`
- Read `clock.now_ns()`, `clock.tick_count()`, `clock.speed_multiplier()`, `clock.mode()`, `clock.is_step_pending()`
- Compute actual speed using `RealTimeGovernor::take_speed_snapshot()` / `compute_speed()` across frames
To support speed snapshot computation across frames, `GuiState` will hold two `SpeedSnapshot` instances:
```rust
pub speed_snap_prev: Option<SpeedSnapshot>,
pub speed_snap_curr: Option<SpeedSnapshot>,
```
### 2. TimingControls Component (`src/gui/components.rs`)
New component `TimingControls` with:
#### Speed Slider (Logarithmic Scale)
- Slider range: logarithmic from 0.001× to 100.0×
- Uses `egui::Slider` with custom logarithmic mapping
- Position 0.0 → 0.001×, position 1.0 → 100.0×
- Special "MaxSpeed" position at the far right
- Calls `clock.set_speed_multiplier()` on change
- Display: "Speed: 1.00× (actual: 0.98×)"
#### Mode Selector
- Three radio buttons: RealTime / MaxSpeed / SingleStep
- Calls `clock.set_mode()` on selection change
#### Step Controls
- "Step" button, enabled only in SingleStep mode
- Calls `clock.trigger_step()` on click
- Shows "Step pending..." indicator when step is pending
#### Virtual Time Display
- Human-readable format: auto-selects µs, ms, or s
- Shows tick count
- Shows target vs actual speed
### 3. Integration (`src/gui/mod.rs`)
Add `timing_controls: TimingControls` to `GuiComponents` and call `render_timing_controls()` between the control panel and memory sections.
### 4. Console Commands (`src/gui/console.rs`)
New commands in `execute_command()`:
| Command | Description |
|---------|-------------|
| `speed <multiplier>` | Set speed multiplier (e.g., `speed 0.5`) |
| `speed` | Show current speed |
| `mode <realtime\|maxspeed\|step>` | Set simulation mode |
| `mode` | Show current mode |
| `step` | Trigger a single step (SingleStep mode) |
| `time` | Show virtual time and tick count |
Also add keyboard shortcuts:
- `+`/`-` already exist for frequency; add new shortcuts for speed:
- Keep existing `+`/`-` for frequency control (unchanged)
### Logarithmic Slider Mapping
The slider position `t` (0.0 to 1.0) maps to speed multiplier via:
```
t=0.00 → 0.001×
t=0.25 → 0.01×
t=0.50 → 0.1×
t=0.75 → 1.0×
t=0.90 → 10.0×
t=1.00 → 100.0×
```
Formula: `speed = 10^(t * 5 - 3)` gives range [0.001, 100.0]
For MaxSpeed mode, we'll use a separate toggle rather than a slider position.
## Implementation Order
1. Add `TimingState` to `src/gui/state.rs`
2. Add `TimingControls` component to `src/gui/components.rs`
3. Integrate into `src/gui/mod.rs`
4. Add console commands to `src/gui/console.rs`
5. Build and test