feat: migrate to parking_lot mutex and add system control architecture

This commit is contained in:
Jan-Peter von Hunnius 2026-02-28 18:27:27 +01:00
parent 14060e15e5
commit 54144d10e9
29 changed files with 2387 additions and 1130 deletions

View file

@ -0,0 +1,296 @@
# Observer Pattern and UI Layout Configuration Implementation Plan
## Overview
This plan implements two key improvements to the rusty_emu project:
1. **Observer Pattern**: Replace inefficient polling with event-driven state updates
2. **UI Layout Configuration**: Enable configurable GUI layouts from JSON config files
## Current Issues
### Performance Issues
- Console polls system state at 100ms intervals (inefficient)
- GUI uses `try_lock()` but still has potential contention
- No way to configure GUI layout from JSON config
### Architecture Limitations
- Tight coupling between components and UI
- No standardized way to notify UI of state changes
- Hardcoded UI layouts
## Solution Architecture
### Observer Pattern Implementation
```mermaid
graph TD
A[SystemObserver Trait] --> B[CPU Observer]
A --> C[RAM Observer]
A --> D[ROM Observer]
B --> E[ConfigurableSystem]
C --> E
D --> E
E --> F[Console UI]
E --> G[GUI Interface]
F --> H[Event-driven Updates]
G --> H
```
### UI Layout Configuration
```mermaid
graph LR
A[SystemConfig JSON] --> B[UI Layout Section]
B --> C[Component Positions]
B --> D[Component Sizes]
B --> E[Display Options]
C --> F[GUI Renderer]
D --> F
E --> F
```
## Implementation Details
### 1. SystemObserver Trait (Fine-grained with Filtering)
```rust
#[derive(Debug, Clone)]
pub enum ObserverFilter {
All,
CpuOnly,
MemoryOnly,
StateChangesOnly,
RegisterChangesOnly,
}
pub trait SystemObserver: Send + Sync {
fn get_filter(&self) -> ObserverFilter { return ObserverFilter::All; }
fn on_state_change(&self, component: &str, old_state: ComponentState, new_state: ComponentState);
fn on_ram_change(&self, chip: &str, bank: usize, address: u8, old_value: u8, new_value: u8);
fn on_rom_change(&self, chip: &str, address: u16, old_value: u8, new_value: u8);
fn on_cpu_register_change(&self, cpu: &str, register: &str, old_value: u8, new_value: u8);
fn on_cpu_pc_change(&self, cpu: &str, old_pc: u16, new_pc: u16);
fn on_cpu_instruction_executed(&self, cpu: &str, instruction: u8, pc: u16);
}
```
### 2. Enhanced SystemConfig
```rust
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SystemConfig {
pub name: String,
pub description: String,
pub version: String,
pub metadata: HashMap<String, serde_json::Value>,
pub components: HashMap<String, ComponentConfig>,
pub connections: HashMap<String, ConnectionConfig>,
pub layout: Option<LayoutConfig>,
// NEW: UI Layout configuration
pub ui_layout: Option<UiLayoutConfig>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UiLayoutConfig {
pub console: Option<ConsoleLayoutConfig>,
pub gui: Option<GuiLayoutConfig>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GuiLayoutConfig {
pub components: HashMap<String, ComponentLayoutConfig>,
pub grid_size: Option<[usize; 2]>,
pub refresh_rate_ms: Option<u64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ComponentLayoutConfig {
pub position: [usize; 2],
pub size: [usize; 2],
pub visible: Option<bool>,
pub display_format: Option<String>,
}
```
### 3. Observer Registration in ConfigurableSystem
```rust
pub struct ConfigurableSystem {
config: SystemConfig,
components: HashMap<String, Arc<Mutex<Box<dyn Component>>>>,
is_running: Arc<Mutex<bool>>,
component_handles: Arc<Mutex<Option<ComponentHandles>>>,
// NEW: Observer registry
observers: Arc<Mutex<Vec<Box<dyn SystemObserver>>>>,
}
```
### 4. Component Integration
Each component will notify observers of state changes:
- **Intel4004 CPU**: Register changes, PC changes, instruction execution
- **Intel4001 ROM**: Memory reads, address changes
- **Intel4002 RAM**: Memory reads/writes, I/O changes
### 5. UI Updates
#### Console Updates (Performance Target: 50% CPU reduction, sub-10ms responsiveness)
- Replace 100ms polling with event-driven updates using observer pattern
- Observer receives notifications and updates display immediately
- Implement filtering to reduce unnecessary UI updates
- Target: Reduce CPU usage by 50% compared to current polling
- Target: Update responsiveness to under 10ms for state changes
#### GUI Updates
- Use layout configuration from JSON for component positioning/sizing
- Position components according to config (basic implementation)
- Show/hide components based on config visibility settings
- Use observer pattern for real-time updates
- Support configurable refresh rates from UI layout config
## Configuration Examples
### Enhanced JSON Config
```json
{
"name": "IntelMcs4",
"description": "Basic MCS-4 System with CPU, Clock, 2 ROMs, and 1 RAM",
"version": "1.0",
"metadata": {
"author": "RustyEmu",
"created": "2024-01-01",
"cpu_speed": 750000,
"architecture": "mcs4",
"rom_count": 2,
"ram_count": 1
},
"components": {
"CPU_4004": {
"single": {
"component_type": "intel_4004",
"name": "CPU_4004",
"properties": {
"clock_speed": 750000
}
}
}
// ... other components
},
"connections": {
// ... existing connections
},
"layout": {
"grid_size": [10, 10],
"positions": {
"cpu": [1, 1],
"clock": [0, 0],
"rom1": [2, 0],
"rom2": [3, 0],
"ram": [2, 2]
}
},
"ui_layout": {
"console": {
"refresh_rate_ms": 50,
"show_ram": true,
"show_registers": true,
"show_system_info": true
},
"gui": {
"grid_size": [20, 20],
"components": {
"CPU_4004": {
"position": [1, 1],
"size": [20, 10],
"visible": true,
"display_format": "hex"
},
"RAM_4002": {
"position": [3, 2],
"size": [25, 15],
"visible": true,
"display_format": "hex"
},
"ROM_4001_1": {
"position": [2, 0],
"size": [20, 8],
"visible": true,
"display_format": "hex"
}
},
"refresh_rate_ms": 60
}
}
}
```
## Benefits
### Performance Improvements
- **Reduced CPU usage**: Event-driven vs polling
- **Better responsiveness**: Immediate updates vs 100ms delays
- **Less contention**: Observer pattern reduces lock contention
### User Experience
- **Configurable layouts**: Users can customize UI arrangement
- **Persistent settings**: Layouts saved in config files
- **Flexible display options**: Show/hide components, change formats
### Architecture Benefits
- **Loose coupling**: Components don't depend on UI
- **Extensibility**: Easy to add new observers
- **Maintainability**: Clear separation of concerns
## Implementation Steps
1. **Add SystemObserver trait** to `system_config.rs`
2. **Extend SystemConfig** with UI layout configuration
3. **Add observer registration** to `ConfigurableSystem`
4. **Implement observer notifications** in Intel4004 CPU
5. **Implement observer notifications** in Intel4001 ROM
6. **Implement observer notifications** in Intel4002 RAM
7. **Update console.rs** to use observer pattern
8. **Update GUI** to use observer pattern and layout configuration
9. **Add UI layout configuration** to existing JSON configs
10. **Test** the observer pattern and UI layout system
11. **Update documentation** with new features
## Testing Strategy
### Unit Tests
- Test observer registration and notification
- Test UI layout configuration parsing
- Test component state change notifications
### Integration Tests
- Test console with observer pattern
- Test GUI with layout configuration
- Test end-to-end state change propagation
### Performance Tests
- Measure CPU usage reduction
- Test responsiveness improvements
- Validate lock contention reduction
## Backward Compatibility
- Existing configs without `ui_layout` section will use defaults (console: 100ms, current GUI layout)
- Observer pattern is additive - doesn't break existing code, components work without observers
- ConfigurableSystem will handle missing `ui_layout` gracefully with sensible defaults
- Gradual migration path: existing configs continue to work, new configs get enhanced features
- No breaking changes to existing JSON configs - only additive new section
## Future Enhancements
- **Multiple observer types**: Different observers for different concerns
- **Layout templates**: Predefined layouts for different use cases
- **Dynamic layout editing**: Runtime layout modification
- **Observer filtering**: Selective notification based on component types

View file

@ -0,0 +1,218 @@
# System Control Architecture Design
## Overview
This document outlines the architecture for implementing enhanced system start/stop/pause controls for the Intel MCS-4 emulator. The design provides centralized system management with fine-grained control over execution state and clock parameters.
## System Architecture
```mermaid
graph TB
subgraph "System Controller Layer"
SC[SystemController Trait]
EC[ExecutionController]
SS[SystemState Enum]
end
subgraph "System Layer"
CS[ConfigurableSystem]
SF[SystemFactory]
end
subgraph "Component Layer"
CPU[Intel4004]
CLK1[GenericClock]
CLK2[TwoPhaseClock]
ROM[Intel4001]
RAM[Intel4002]
end
subgraph "Interface Layer"
GUI[GUI Control Panel]
CON[Console Commands]
KB[Keyboard Shortcuts]
end
SC --> EC
EC --> CS
CS --> CPU
CS --> CLK1
CS --> CLK2
CS --> ROM
CS --> RAM
GUI --> SC
CON --> SC
KB --> SC
```
## Core Components
### 1. SystemController Trait
Defines the interface for system-wide control operations:
```rust
pub trait SystemController {
fn start(&mut self) -> Result<(), String>;
fn stop(&mut self) -> Result<(), String>;
fn pause(&mut self) -> Result<(), String>;
fn resume(&mut self) -> Result<(), String>;
fn is_running(&self) -> bool;
fn is_paused(&self) -> bool;
fn set_clock_frequency(&mut self, frequency: f64) -> Result<(), String>;
fn set_clock_enabled(&mut self, enabled: bool) -> Result<(), String>;
fn get_system_state(&self) -> SystemState;
fn get_clock_frequency(&self) -> f64;
fn get_clock_enabled(&self) -> bool;
}
```
### 2. SystemState Enum
Tracks the overall system execution state:
```rust
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum SystemState {
Stopped,
Running,
Paused,
Error(String),
}
```
### 3. ExecutionController
Manages system lifecycle and coordinates component states:
```rust
pub struct ExecutionController {
system_state: SystemState,
clock_frequency: f64,
clock_enabled: bool,
components: HashMap<String, Arc<Mutex<Box<dyn Component>>>>,
}
```
## Component Enhancements
### Clock Components
**GenericClock & TwoPhaseClock Enhancements:**
- Add `paused` boolean field
- Implement `pause()` and `resume()` methods
- Add dynamic frequency adjustment with `set_frequency(f64)`
- Add `enable()` and `disable()` methods for power control
- Update `update()` methods to respect pause state
### CPU Component
**Intel4004 Enhancements:**
- Add `paused` boolean field
- Implement `pause()` to halt instruction execution
- Implement `resume()` to continue instruction execution
- Update `update()` to check pause state before executing instructions
- Maintain clock edge detection during pause for seamless resume
### Memory Components
**Intel4001 & Intel4002 Enhancements:**
- Add `paused` boolean field
- Implement `pause()` and `resume()` methods
- Update `update()` to respect pause state
- Ensure memory operations complete current cycle before pausing
## Interface Updates
### Console Commands
New console commands:
- `pause` / `p` - Pause system execution
- `resume` - Resume system execution
- `clock <freq>` - Set clock frequency (e.g., `clock 500000`)
- `clock on` / `clock off` - Enable/disable clock
- `speed +` / `speed -` - Increase/decrease clock frequency by 50%
### GUI Controls
New GUI control panel:
- System state indicator (Stopped/Running/Paused)
- Start/Stop/Pause/Resume buttons
- Clock frequency slider (100Hz - 10MHz range)
- Clock enable/disable toggle
- Real-time frequency display
- Keyboard shortcuts (Space=pause/resume, +/- for frequency)
## Configuration Schema
Extended JSON configuration with clock control:
```json
{
"clock_control": {
"initial_frequency": 750000,
"min_frequency": 1000,
"max_frequency": 10000000,
"frequency_step": 50000,
"auto_start": true
}
}
```
## Implementation Strategy
### Phase 1: Core Infrastructure
1. Implement SystemController trait
2. Create SystemState enum
3. Build ExecutionController
4. Update ConfigurableSystem
### Phase 2: Component Updates
1. Update clock components with pause/resume
2. Update CPU with execution control
3. Update memory components
4. Add dynamic frequency adjustment
### Phase 3: Interface Integration
1. Update console with new commands
2. Enhance GUI with control panel
3. Add keyboard shortcuts
4. Update configuration handling
### Phase 4: Testing & Documentation
1. Create comprehensive test suite
2. Update all documentation
3. Verify backwards compatibility
## Key Design Decisions
### Pause Behavior
- Complete system freeze including clock signals
- Components maintain state for seamless resume
- Clock edges are tracked but not propagated during pause
### Frequency Adjustment
- Dynamic adjustment during runtime
- Smooth transitions without glitches
- Validation against component limits
### State Management
- Centralized state tracking
- Thread-safe state updates
- Consistent state across all components
## Benefits
1. **Enhanced Control**: Fine-grained system management
2. **Dynamic Adjustment**: Runtime frequency changes
3. **Better Debugging**: Pause/resume for analysis
4. **User Experience**: Intuitive controls in both interfaces
5. **Extensibility**: Clean architecture for future enhancements
## Compatibility
- Maintains existing Component trait
- Backwards compatible with current configurations
- No breaking changes to existing APIs
- Optional features with sensible defaults