feat: migrate to parking_lot mutex and add system control architecture
This commit is contained in:
parent
14060e15e5
commit
54144d10e9
29 changed files with 2387 additions and 1130 deletions
296
plans/observer_pattern_and_ui_layout.md
Normal file
296
plans/observer_pattern_and_ui_layout.md
Normal 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
|
||||
218
plans/system_control_architecture.md
Normal file
218
plans/system_control_architecture.md
Normal 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue