Unified the 400x state machine for address latching

Fixed timing issues
This commit is contained in:
Jan-Peter von Hunnius 2025-11-14 18:51:10 +01:00
parent e17d6ad177
commit 633463e370
26 changed files with 11904 additions and 2471 deletions

View file

@ -1,7 +1,6 @@
# Intel 400x Common Functionality
This module provides shared functionality for all Intel 400x series chips (4001, 4002, 4003, 4004). It contains common
traits, utilities, and behaviors that are used across multiple components.
This module provides shared functionality for all Intel 400x series chips (4001, 4002, 4003, 4004) through a unified state machine architecture. It contains common traits, utilities, and behaviors that are used across multiple components.
## Purpose
@ -12,13 +11,114 @@ The Intel 400x series shares many common characteristics:
- **12-bit address space** (8-bit addresses in two 4-bit cycles)
- **Common timing constraints** and access patterns
- **Similar pin configurations** and control signals
- **Shared state machine patterns** for memory operations
- **Unified state machine patterns** for all operations
Rather than duplicating this code in each component, it's centralized here for maintainability and consistency.
## Architecture
## Unified State Machine Architecture
### Trait-Based Design
### Overview
The Intel 400x series now uses a unified state machine approach that replaces individual chip state machines with a single, extensible framework. This approach provides several benefits:
1. **Consistency**: All components follow the same basic state transition patterns
2. **Maintainability**: Common logic is centralized in the state machine engine
3. **Extensibility**: New chip types can be added by implementing the `Intel400xComponentBehavior` trait
4. **Testability**: Components can be tested independently with mock behaviors
### Key Components
#### Intel400xComponentBehavior Trait
This trait defines the interface that all Intel 400x components must implement to work with the unified state machine architecture. It allows each component to provide its own specific behavior while still following the common state machine framework.
```rust
pub trait Intel400xComponentBehavior {
fn get_component_type(&self) -> Intel400xComponentType;
fn on_state_entry(&mut self, state: Intel400xUnifiedState);
fn on_state_exit(&mut self, state: Intel400xUnifiedState);
fn handle_component_event(&mut self, event: Intel400xEvent) -> bool;
fn execute_state_logic(&mut self, state: Intel400xUnifiedState);
fn responds_to_address(&self) -> bool;
}
```
#### Intel400xComponentType
Enumeration that identifies the specific type of Intel 400x component being modeled:
```rust
pub enum Intel400xComponentType {
Intel4001, // ROM (Read-Only Memory)
Intel4002, // RAM (Random Access Memory)
Intel4003, // Shift Register
Intel4004, // CPU (Central Processing Unit)
}
```
#### Intel400xUnifiedState
Enumeration representing all possible states for any Intel 400x component in the unified state machine:
```rust
pub enum Intel400xUnifiedState {
// Common states (shared across all components)
Idle,
AddressPhase,
WaitLatency,
DriveData,
// Component-specific states
ReadData, // Intel 4002 (RAM) specific
WriteData, // Intel 4002 (RAM) specific
OutputPort, // Intel 4002 (RAM) specific
ShiftData, // Intel 4003 (Shift Register) specific
LoadData, // Intel 4003 (Shift Register) specific
FetchInstruction, // Intel 4004 (CPU) specific
ExecuteInstruction, // Intel 4004 (CPU) specific
}
```
#### Intel400xEvent
Enumeration representing events that can trigger state transitions:
```rust
pub enum Intel400xEvent {
ClockPhi1Rising,
ClockPhi1Falling,
ClockPhi2Rising,
ClockPhi2Falling,
SyncActive,
SyncInactive,
ChipSelect,
ChipDeselect,
ResetActive,
ResetInactive,
AddressComplete,
LatencyElapsed,
DataReady,
OperationComplete,
}
```
#### Intel400xStateMachine
The core state machine engine that manages state transitions and coordinates with component behaviors:
```rust
pub struct Intel400xStateMachine {
component_type: Intel400xComponentType,
current_state: Intel400xUnifiedState,
previous_state: Intel400xUnifiedState,
address_high_nibble: Option<u8>,
address_low_nibble: Option<u8>,
address_latch_time: Option<Instant>,
access_time: Duration,
}
```
## Trait-Based Design
The common functionality is organized around several key traits:
@ -28,19 +128,9 @@ Intel400xDataBus - Data bus read/write operations
Intel400xAddressHandling - Address latching and assembly
Intel400xControlPins - Control signal reading
Intel400xResetHandling - Reset signal handling
Intel400xTimingState - Memory operation state machines
Intel400xTimingState - Memory operation state management
```
### State Machine
All Intel 400x memory operations follow a common pattern:
```
Idle → AddressPhase → WaitLatency → DriveData → Idle
```
Each phase has specific timing requirements and bus usage patterns.
## Core Traits
### Intel400xClockHandling
@ -139,8 +229,8 @@ pub trait Intel400xResetHandling {
fn get_base(&self) -> &BaseComponent;
// Reset operations
fn handle_reset(&self, reset_pin_name: &str) -> bool;
fn perform_reset(&self); // Component-specific reset logic
fn handle_reset(&mut self, reset_pin_name: &str) -> bool;
fn perform_reset(&mut self); // Component-specific reset logic
}
```
@ -156,8 +246,8 @@ Manages memory operation timing and state machines:
```rust
pub trait Intel400xTimingState {
// State management
fn get_timing_state(&self) -> TimingState;
fn set_timing_state(&mut self, state: TimingState);
fn get_timing_state(&self) -> MemoryState;
fn set_timing_state(&mut self, state: MemoryState);
// Address tracking
fn get_address_latch_time(&self) -> Option<Instant>;
@ -179,6 +269,31 @@ pub trait Intel400xTimingState {
- Timing constraint management
- Address tracking and validation
## State Machine Operation
### State Transition Logic
The unified state machine operates by:
1. Receiving events from the component or external sources
2. Determining the next state based on current state and event
3. Calling appropriate state entry/exit methods on the component behavior
4. Executing state-specific logic through the component behavior
### Common State Transitions
1. **Idle → AddressPhase**: Triggered by chip select when component responds to address
2. **AddressPhase → WaitLatency**: After both address nibbles are latched
3. **WaitLatency → Component-Specific State**: After access time has elapsed
4. **Component-Specific State → Idle**: When operation completes
### Component-Specific Behaviors
- **Intel 4001 (ROM)**: Transitions to DriveData to provide read-only data
- **Intel 4002 (RAM)**: Transitions to ReadData, WriteData, or OutputPort based on operation
- **Intel 4003 (Shift Register)**: Ignores address transmission, goes directly to ShiftData
- **Intel 4004 (CPU)**: Uses FetchInstruction and ExecuteInstruction states
## Timing Constants
### Standard Timing Values
@ -201,13 +316,11 @@ Each component type uses appropriate timing constants:
- **Shift Register (4003)**: 200ns fast access time
- **CPU (4004)**: Internal operation timing
## State Machine
### Memory Operation States
## Memory Operation States
```rust
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum TimingState {
pub enum MemoryState {
Idle, // No memory operation in progress
AddressPhase, // Currently latching address nibbles
WaitLatency, // Address latched, waiting for access time
@ -215,22 +328,6 @@ pub enum TimingState {
}
```
### State Transition Logic
1. **Idle → AddressPhase**: Triggered by SYNC high + Φ1 rising edge
2. **AddressPhase → WaitLatency**: After both address nibbles latched
3. **WaitLatency → DriveData**: After access time has elapsed
4. **DriveData → Idle**: On Φ2 falling edge (bus tri-stated)
### Hardware Timing
Each state has specific timing requirements:
- **Address Setup**: 100ns minimum before latching
- **Data Valid**: 200ns maximum from address valid to data available
- **Bus Hold**: Data held until Φ2 falling edge
- **Tri-state Delay**: 150ns maximum to high impedance after disable
## Utility Functions
### Pin Operations
@ -256,11 +353,60 @@ All pin operations include proper error handling:
- **Pin not found**: Return appropriate error messages
- **Invalid states**: Graceful degradation
## Usage Examples
### Implementing the Intel400xComponentBehavior Trait
```rust
struct MyComponent {
// Component fields...
state_machine: Intel400xStateMachine,
}
impl Intel400xComponentBehavior for MyComponent {
fn get_component_type(&self) -> Intel400xComponentType {
Intel400xComponentType::Intel4001 // Example type
}
fn on_state_entry(&mut self, state: Intel400xUnifiedState) {
match state {
Intel400xUnifiedState::AddressPhase => {
// Prepare for address latching
}
Intel400xUnifiedState::DriveData => {
// Prepare for data transfer
}
_ => {}
}
}
// ... implement other methods
}
```
### Using the Unified State Machine
```rust
// Create a state machine for an Intel 4001 ROM chip
let mut state_machine = Intel400xStateMachine::new(
Intel400xComponentType::Intel4001,
Duration::from_nanos(500)
);
// Process a chip select event
let new_state = process_event_direct(
&mut state_machine,
Intel400xEvent::ChipSelect
);
assert_eq!(new_state, Intel400xUnifiedState::AddressPhase);
```
## Testing
### Comprehensive Test Suite
The common functionality is thoroughly tested with:
The unified state machine is thoroughly tested with:
1. **Unit Tests**: Test individual functions and algorithms
2. **Mock Tests**: Test with controlled hardware inputs
@ -269,76 +415,26 @@ The common functionality is thoroughly tested with:
### Testable Areas
- **Timing constants validation**
- **Address assembly algorithms**
- **State machine transitions**
- **Address latching algorithms**
- **Component-specific behaviors**
- **Clock edge detection accuracy**
- **Data bus bit operations**
- **Pin operation safety**
### Mock System
## Benefits of the Unified Approach
A comprehensive mock system allows testing without real hardware:
```rust
// Create mock component for testing
let mut mock_component = MockIntel400xComponent::new("TestComponent");
// Set up test scenario
mock_component.set_clock_values(PinValue::High, PinValue::Low);
// Test behavior
assert!(mock_component.is_phi1_rising_edge(PinValue::Low));
```
## Usage in Components
### Implementation Pattern
Components implement the relevant traits:
```rust
impl Intel400xClockHandling for MyComponent {
fn get_base(&self) -> &BaseComponent {
&self.base
}
}
impl Intel400xDataBus for MyComponent {
fn get_base(&self) -> &BaseComponent {
&self.base
}
fn read_data_bus(&self) -> u8 {
// Use common data bus reading logic
let mut data = 0;
for i in 0..4 {
if let Ok(pin) = self.get_base().get_pin(&format!("D{}", i)) {
if let Ok(pin_guard) = pin.lock() {
if pin_guard.read() == PinValue::High {
data |= 1 << i;
}
}
}
}
data & 0x0F
}
}
```
### Benefits
1. **Code Reuse**: Common functionality shared across components
2. **Consistency**: Uniform behavior across all 400x components
3. **Maintainability**: Changes to common logic update all components
4. **Testability**: Common code can be tested once and reused
5. **Type Safety**: Traits ensure proper implementation
1. **Code Reuse**: Common state transition logic is shared across all components
2. **Consistency**: All components follow the same timing and state patterns
3. **Maintainability**: Changes to common behavior only need to be made in one place
4. **Extensibility**: New chip types can be added without modifying the core state machine
5. **Testability**: The state machine can be tested independently of specific components
## Hardware Accuracy
### Timing Considerations
The common code implements hardware-accurate timing where possible:
The unified state machine implements hardware-accurate timing where possible:
- **Clock Edge Detection**: Proper Φ1/Φ2 edge detection
- **Address Latching**: Two-phase address capture
@ -356,19 +452,19 @@ The common code implements hardware-accurate timing where possible:
### Planned Improvements
1. **Enhanced Timing Simulation**
- More accurate sub-nanosecond timing
- Better clock phase relationship modeling
- Improved signal propagation delays
- More accurate sub-nanosecond timing
- Better clock phase relationship modeling
- Improved signal propagation delays
2. **Extended Component Support**
- Support for additional Intel 400x variants
- Enhanced I/O device support
- Better peripheral modeling
- Support for additional Intel 400x variants
- Enhanced I/O device support
- Better peripheral modeling
3. **Testing Improvements**
- More sophisticated mock scenarios
- Better timing verification tools
- Enhanced debugging capabilities
- More sophisticated mock scenarios
- Better timing verification tools
- Enhanced debugging capabilities
### Extension Points
@ -403,5 +499,4 @@ The common functionality depends on:
- **Shared Code**: No duplication across components
- **Efficient State Storage**: Compact state representation
This common functionality module provides a solid foundation for all Intel 400x components while maintaining high
performance and hardware accuracy.
This unified state machine architecture provides a solid foundation for all Intel 400x components while maintaining high performance and hardware accuracy.