rusty_emu/plans/phase8_gui_controls.md
Jan-Peter von Hunnius 08f53d68fe 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.
2026-05-14 21:00:22 +02:00

117 lines
4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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