# Intel 400x Common Functionality 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 The Intel 400x series shares many common characteristics: - **Two-phase clock operation** (Φ1, Φ2) - **4-bit data bus** with multiplexed address/data - **12-bit address space** (8-bit addresses in two 4-bit cycles) - **Common timing constraints** and access patterns - **Similar pin configurations** and control signals - **Unified state machine patterns** for all operations Rather than duplicating this code in each component, it's centralized here for maintainability and consistency. ## Unified State Machine Architecture ### 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 FetchByte1, // Intel 4004 (CPU) specific — fetching first byte FetchByte2, // Intel 4004 (CPU) specific — fetching second byte of 2-byte instruction Execute, // Intel 4004 (CPU) specific — executing decoded instruction } ``` #### 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, address_low_nibble: Option, address_latch_time: Option, access_time: Duration, } ``` ## Trait-Based Design The common functionality is organized around several key traits: ``` Intel400xClockHandling - Clock edge detection and timing Intel400xDataBus - Data bus read/write operations Intel400xAddressHandling - Address latching and assembly Intel400xControlPins - Control signal reading Intel400xResetHandling - Reset signal handling Intel400xTimingState - Memory operation state management ``` ## Core Traits ### Intel400xClockHandling Handles the two-phase clock system used by all 400x components: ```rust pub trait Intel400xClockHandling { fn get_base(&self) -> &BaseComponent; // Clock edge detection fn is_phi1_rising_edge(&self, prev_phi1: PinValue) -> bool; fn is_phi1_falling_edge(&self, prev_phi1: PinValue) -> bool; fn is_phi2_rising_edge(&self, prev_phi2: PinValue) -> bool; fn is_phi2_falling_edge(&self, prev_phi2: PinValue) -> bool; // Clock state management fn update_clock_states(&self, prev_phi1: &mut PinValue, prev_phi2: &mut PinValue); } ``` **Key Features:** - Edge detection for both clock phases - Previous state tracking for transition detection - Thread-safe pin access ### Intel400xDataBus Manages the 4-bit multiplexed address/data bus: ```rust pub trait Intel400xDataBus { fn get_base(&self) -> &BaseComponent; // Bus operations fn read_data_bus(&self) -> u8; // Read 4-bit value from D0-D3 fn write_data_bus(&self, data: u8); // Drive 4-bit value on D0-D3 fn tri_state_data_bus(&self); // Set bus to high impedance } ``` **Key Features:** - Safe pin access with error handling - Driver name tracking for debugging - Bus contention avoidance ### Intel400xAddressHandling Handles the two-phase addressing used by 400x components: ```rust pub trait Intel400xAddressHandling { fn get_base(&self) -> &BaseComponent; // Address operations fn assemble_full_address(&self, high_nibble: Option, low_nibble: Option) -> Option; fn handle_address_latching(&self, nibble: u8, ...); // Complex latching logic fn handle_latency_wait(&self, address_latch_time: &Option, access_time: Duration) -> bool; } ``` **Key Features:** - Two-phase address latching (high nibble, then low nibble) - Timing-aware address assembly - Access time validation ### Intel400xControlPins Reads control signals common to all 400x components: ```rust pub trait Intel400xControlPins { fn get_base(&self) -> &BaseComponent; // Control signal reading fn read_sync_pin(&self) -> bool; // SYNC signal state fn read_cm_rom_pin(&self) -> bool; // CM-ROM chip select fn read_reset_pin(&self) -> bool; // RESET signal state } ``` **Key Features:** - Safe pin reading with fallback values - Consistent pin naming across components ### Intel400xResetHandling Provides reset functionality for all 400x components: ```rust pub trait Intel400xResetHandling { fn get_base(&self) -> &BaseComponent; // Reset operations fn handle_reset(&mut self, reset_pin_name: &str) -> bool; fn perform_reset(&mut self); // Component-specific reset logic } ``` **Key Features:** - System-wide reset signal handling - Component-specific reset behaviors ### Intel400xTimingState Manages memory operation timing and state machines: ```rust pub trait Intel400xTimingState { // State management fn get_timing_state(&self) -> MemoryState; fn set_timing_state(&mut self, state: MemoryState); // Address tracking fn get_address_latch_time(&self) -> Option; fn set_address_latch_time(&mut self, time: Option); // Address components fn get_full_address_ready(&self) -> bool; fn get_address_high_nibble(&self) -> Option; fn get_address_low_nibble(&self) -> Option; // Timing configuration fn get_access_time(&self) -> Duration; } ``` **Key Features:** - Unified state machine interface - 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 FetchByte1, FetchByte2, and Execute states for instruction processing ## Timing Constants ### Standard Timing Values ```rust impl TimingConstants { pub const DEFAULT_ACCESS_TIME: Duration = Duration::from_nanos(500); // 500ns default pub const FAST_ACCESS_TIME: Duration = Duration::from_nanos(200); // 200ns for shift registers pub const ADDRESS_SETUP: Duration = Duration::from_nanos(100); // Address setup time pub const DATA_VALID: Duration = Duration::from_nanos(200); // Data valid delay } ``` ### Usage in Components Each component type uses appropriate timing constants: - **ROM (4001)**: 500ns typical access time - **RAM (4002)**: 500ns access time with refresh overhead - **Shift Register (4003)**: 200ns fast access time - **CPU (4004)**: Internal operation timing ## Memory Operation States ```rust #[derive(Debug, Clone, Copy, PartialEq)] pub enum MemoryState { Idle, // No memory operation in progress AddressPhase, // Currently latching address nibbles WaitLatency, // Address latched, waiting for access time DriveData, // Latency elapsed, driving data on bus } ``` ## Utility Functions ### Pin Operations ```rust pub mod utils { // Safe pin operations with error handling pub fn is_pin_high(pin: &Arc>) -> bool; pub fn is_pin_high_z(pin: &Arc>) -> bool; pub fn read_pin_safe(pin: &Arc>, default: PinValue) -> PinValue; pub fn set_pin_driver_safe(pin: &Arc>, driver_name: String, value: PinValue); // Component naming and identification pub fn create_driver_name(component_name: &str, suffix: &str) -> String; } ``` ### Error Handling All pin operations include proper error handling: - **Lock failures**: Return safe default values - **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 unified state machine is thoroughly tested with: 1. **Unit Tests**: Test individual functions and algorithms 2. **Mock Tests**: Test with controlled hardware inputs 3. **Property Tests**: Verify behavioral properties 4. **Integration Tests**: Test with real component implementations ### Testable Areas - **State machine transitions** - **Address latching algorithms** - **Component-specific behaviors** - **Clock edge detection accuracy** - **Data bus bit operations** - **Pin operation safety** ## Benefits of the Unified Approach 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 unified state machine implements hardware-accurate timing where possible: - **Clock Edge Detection**: Proper Φ1/Φ2 edge detection - **Address Latching**: Two-phase address capture - **Access Time Simulation**: Configurable access latencies - **Bus State Management**: Proper drive/tri-state timing ### Limitations - **Rust Timing**: Limited by Rust's timing resolution - **Threading**: Simulation runs in single thread vs. hardware parallelism - **Signal Propagation**: Simplified signal timing for simulation ## Future Enhancements ### Planned Improvements 1. **Enhanced Timing Simulation** - 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 3. **Testing Improvements** - More sophisticated mock scenarios - Better timing verification tools - Enhanced debugging capabilities ### Extension Points The trait-based design makes it easy to: - **Add New Components**: Implement the required traits - **Enhance Timing**: Modify timing constants and logic - **Improve Testing**: Add new mock scenarios and test utilities - **Extend Functionality**: Add new common behaviors as needed ## Dependencies The common functionality depends on: - **Base Component System**: For pin management and lifecycle - **Pin Abstraction**: For signal state management - **Timing Utilities**: For duration and instant handling - **Error Handling**: For robust operation ## Performance ### Optimization Features - **Efficient Pin Access**: Minimized lock contention - **Fast State Transitions**: Optimized state machine - **Minimal Allocations**: Reuse of common data structures - **Lock-Free Algorithms**: Where possible for performance ### Memory Usage - **Small Footprint**: Minimal memory overhead per component - **Shared Code**: No duplication across components - **Efficient State Storage**: Compact state representation This unified state machine architecture provides a solid foundation for all Intel 400x components while maintaining high performance and hardware accuracy.