296 lines
No EOL
8.4 KiB
Markdown
296 lines
No EOL
8.4 KiB
Markdown
# 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 |