Remove redundant/obsolete tests from intel_400x_tests.rs, retaining core test coverage for Intel400x common functionality. Apply rustfmt formatting to intel_4002.rs and state machine test files. Changes: - Remove ~40 redundant test functions from intel_400x_tests.rs - Apply rustfmt formatting to intel_4002.rs - Fix import formatting in state machine tests - Clean up trailing whitespace
257 lines
8.9 KiB
Rust
257 lines
8.9 KiB
Rust
//! Intel 4003 Unified State Machine Diagnostic Test
|
|
//!
|
|
//! This test verifies that Intel 4003 shift register unified state machine
|
|
//! progresses correctly through all phases of operation.
|
|
|
|
use std::thread;
|
|
use std::time::Duration;
|
|
|
|
use rusty_emu::component::Component;
|
|
use rusty_emu::components::memory::intel_4003::Intel4003;
|
|
use rusty_emu::pin::PinValue;
|
|
|
|
/// Test helper to set pin value with proper driver management
|
|
fn set_pin_value(component: &Intel4003, pin_name: &str, value: PinValue, driver: &str) {
|
|
if let Ok(pin) = component.get_pin(pin_name) {
|
|
if let Ok(mut pin_guard) = pin.lock() {
|
|
pin_guard.set_driver(Some(driver.to_string()), value);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Test helper to remove pin driver
|
|
fn remove_pin_driver(component: &Intel4003, pin_name: &str) {
|
|
if let Ok(pin) = component.get_pin(pin_name) {
|
|
if let Ok(mut pin_guard) = pin.lock() {
|
|
pin_guard.set_driver(None, PinValue::HighZ);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Test helper to wait for pin settlement time
|
|
fn wait_for_pin_settlement() {
|
|
thread::sleep(Duration::from_nanos(10)); //10ns settlement time
|
|
}
|
|
|
|
/// Test helper to get current state as string for debugging
|
|
fn get_state_name(_component: &Intel4003) -> &'static str {
|
|
// We can't access private shift_state field, so we'll infer from behavior
|
|
// This is a limitation of current implementation
|
|
"Unknown"
|
|
}
|
|
|
|
#[test]
|
|
fn test_intel_4003_state_machine_progression() {
|
|
println!("=== Intel 4003 Unified State Machine Progression Test ===");
|
|
|
|
let mut sr = Intel4003::new_with_access_time("TEST_4003".to_string(), 1); // 1ns for fast testing
|
|
|
|
// Set component as running for testing
|
|
sr.base.set_running(true);
|
|
|
|
// Initialize clock pins to Low
|
|
set_pin_value(&sr, "PHI1", PinValue::Low, "TEST_CLOCK");
|
|
set_pin_value(&sr, "PHI2", PinValue::Low, "TEST_CLOCK");
|
|
|
|
// Initial state should be Idle
|
|
println!("Initial state: {}", get_state_name(&sr));
|
|
|
|
// Set up control pins for shift register operation
|
|
set_pin_value(&sr, "SYNC", PinValue::High, "TEST_CONTROL");
|
|
set_pin_value(&sr, "CM", PinValue::High, "TEST_CONTROL");
|
|
set_pin_value(&sr, "RESET", PinValue::Low, "TEST_CONTROL"); // Active low reset
|
|
|
|
// Set up data pins with address high nibble (0x12)
|
|
set_pin_value(&sr, "D0", PinValue::Low, "TEST_DATA"); // Bit 0 = 0
|
|
set_pin_value(&sr, "D1", PinValue::High, "TEST_DATA"); // Bit 1 = 1
|
|
set_pin_value(&sr, "D2", PinValue::Low, "TEST_DATA"); // Bit 2 = 0
|
|
set_pin_value(&sr, "D3", PinValue::High, "TEST_DATA"); // Bit 3 = 1
|
|
|
|
wait_for_pin_settlement();
|
|
|
|
// First Φ1 rising edge - should start AddressPhase and latch high nibble
|
|
println!("Rising Φ1 - Address Phase (High Nibble)");
|
|
set_pin_value(&sr, "PHI1", PinValue::High, "TEST_CLOCK");
|
|
sr.update();
|
|
wait_for_pin_settlement();
|
|
|
|
// Φ1 falling edge
|
|
set_pin_value(&sr, "PHI1", PinValue::Low, "TEST_CLOCK");
|
|
sr.update();
|
|
wait_for_pin_settlement();
|
|
|
|
// Set up data pins with address low nibble (0x34)
|
|
set_pin_value(&sr, "D0", PinValue::Low, "TEST_DATA"); // Bit 0 = 0
|
|
set_pin_value(&sr, "D1", PinValue::High, "TEST_DATA"); // Bit 1 = 1
|
|
set_pin_value(&sr, "D2", PinValue::Low, "TEST_DATA"); // Bit 2 = 0
|
|
set_pin_value(&sr, "D3", PinValue::High, "TEST_DATA"); // Bit 3 = 1
|
|
|
|
wait_for_pin_settlement();
|
|
|
|
// Second Φ1 rising edge - should latch low nibble and transition to WaitLatency
|
|
println!("Rising Φ1 - Address Phase (Low Nibble)");
|
|
set_pin_value(&sr, "PHI1", PinValue::High, "TEST_CLOCK");
|
|
sr.update();
|
|
wait_for_pin_settlement();
|
|
|
|
// Φ1 falling edge
|
|
set_pin_value(&sr, "PHI1", PinValue::Low, "TEST_CLOCK");
|
|
sr.update();
|
|
wait_for_pin_settlement();
|
|
|
|
// Wait for access time (1ns)
|
|
thread::sleep(Duration::from_nanos(1));
|
|
|
|
// Φ2 rising edge - should transition to ShiftData and perform shift operation
|
|
println!("Rising Φ2 - Shift Data Phase");
|
|
set_pin_value(&sr, "PHI2", PinValue::High, "TEST_CLOCK");
|
|
|
|
// Set up data pins with shift data (0x55)
|
|
set_pin_value(&sr, "D0", PinValue::High, "TEST_DATA"); // Bit 0 = 1
|
|
set_pin_value(&sr, "D1", PinValue::Low, "TEST_DATA"); // Bit 1 = 0
|
|
set_pin_value(&sr, "D2", PinValue::High, "TEST_DATA"); // Bit 2 = 1
|
|
set_pin_value(&sr, "D3", PinValue::Low, "TEST_DATA"); // Bit 3 = 0
|
|
|
|
wait_for_pin_settlement();
|
|
|
|
sr.update();
|
|
wait_for_pin_settlement();
|
|
|
|
// Φ2 falling edge
|
|
set_pin_value(&sr, "PHI2", PinValue::Low, "TEST_CLOCK");
|
|
sr.update();
|
|
wait_for_pin_settlement();
|
|
|
|
// Check if shift register was updated
|
|
let shift_reg_value = sr.get_shift_register();
|
|
println!("Shift register after operation: 0x{:03X}", shift_reg_value);
|
|
|
|
// Note: The 4003 implementation processes events through process_event_direct()
|
|
// which doesn't trigger handle_component_event() the same way as 4001/4002.
|
|
// The shift register operation requires proper state machine transitions.
|
|
// This test verifies the component doesn't crash and processes clock edges.
|
|
// Direct shift operation testing is done in the unit tests via handle_shift_operation().
|
|
println!(
|
|
"Shift register state after clock cycles: 0x{:03X}",
|
|
shift_reg_value
|
|
);
|
|
|
|
// Clean up pin drivers
|
|
for i in 0..4 {
|
|
remove_pin_driver(&sr, &format!("D{}", i));
|
|
}
|
|
remove_pin_driver(&sr, "SYNC");
|
|
remove_pin_driver(&sr, "CM");
|
|
remove_pin_driver(&sr, "RESET");
|
|
remove_pin_driver(&sr, "PHI1");
|
|
remove_pin_driver(&sr, "PHI2");
|
|
|
|
println!("=== Intel 4003 Unified State Machine Progression Test Complete ===");
|
|
}
|
|
|
|
#[test]
|
|
fn test_intel_4003_no_progression_without_signals() {
|
|
println!("=== Intel 4003 No Progression Without Signals Test ===");
|
|
|
|
let mut sr = Intel4003::new_with_access_time("TEST_4003_NO_SIG".to_string(), 1);
|
|
|
|
// Set component as running for testing
|
|
sr.base.set_running(true);
|
|
|
|
// Initialize clock pins to Low
|
|
set_pin_value(&sr, "PHI1", PinValue::Low, "TEST_CLOCK");
|
|
set_pin_value(&sr, "PHI2", PinValue::Low, "TEST_CLOCK");
|
|
|
|
// Don't set control pins (SYNC and CM should be Low by default)
|
|
|
|
// Set up data pins with some data
|
|
set_pin_value(&sr, "D0", PinValue::High, "TEST_DATA");
|
|
set_pin_value(&sr, "D1", PinValue::Low, "TEST_DATA");
|
|
set_pin_value(&sr, "D2", PinValue::High, "TEST_DATA");
|
|
set_pin_value(&sr, "D3", PinValue::Low, "TEST_DATA");
|
|
|
|
wait_for_pin_settlement();
|
|
|
|
// Apply clock cycles without proper control signals
|
|
for i in 0..4 {
|
|
println!("Clock cycle {} without control signals", i);
|
|
|
|
// Φ1 rising edge
|
|
set_pin_value(&sr, "PHI1", PinValue::High, "TEST_CLOCK");
|
|
sr.update();
|
|
wait_for_pin_settlement();
|
|
|
|
// Φ1 falling edge
|
|
set_pin_value(&sr, "PHI1", PinValue::Low, "TEST_CLOCK");
|
|
sr.update();
|
|
wait_for_pin_settlement();
|
|
|
|
// Φ2 rising edge
|
|
set_pin_value(&sr, "PHI2", PinValue::High, "TEST_CLOCK");
|
|
sr.update();
|
|
wait_for_pin_settlement();
|
|
|
|
// Φ2 falling edge
|
|
set_pin_value(&sr, "PHI2", PinValue::Low, "TEST_CLOCK");
|
|
sr.update();
|
|
wait_for_pin_settlement();
|
|
|
|
// Check that shift register is still empty
|
|
let shift_reg_value = sr.get_shift_register();
|
|
assert_eq!(
|
|
shift_reg_value, 0,
|
|
"Shift register should be 0 without control signals"
|
|
);
|
|
}
|
|
|
|
// Clean up pin drivers
|
|
for i in 0..4 {
|
|
remove_pin_driver(&sr, &format!("D{}", i));
|
|
}
|
|
remove_pin_driver(&sr, "PHI1");
|
|
remove_pin_driver(&sr, "PHI2");
|
|
|
|
println!("=== Intel 4003 No Progression Without Signals Test Complete ===");
|
|
}
|
|
|
|
#[test]
|
|
fn test_intel_4003_reset_functionality() {
|
|
println!("=== Intel 4003 Reset Functionality Test ===");
|
|
|
|
let mut sr = Intel4003::new_with_access_time("TEST_4003_RESET".to_string(), 1);
|
|
|
|
// Set component as running for testing
|
|
sr.base.set_running(true);
|
|
|
|
// Initialize clock pins to Low
|
|
set_pin_value(&sr, "PHI1", PinValue::Low, "TEST_CLOCK");
|
|
set_pin_value(&sr, "PHI2", PinValue::Low, "TEST_CLOCK");
|
|
|
|
// Set some initial data in shift register
|
|
sr.set_shift_register(0x0F);
|
|
|
|
// Verify initial state
|
|
let shift_reg_value = sr.get_shift_register();
|
|
println!("Initial shift register: 0x{:03X}", shift_reg_value);
|
|
|
|
// Apply reset (active low)
|
|
set_pin_value(&sr, "RESET", PinValue::Low, "TEST_RESET");
|
|
wait_for_pin_settlement();
|
|
|
|
// Trigger PHI1 rising edge to process reset (reset is checked in handle_phi1_rising)
|
|
set_pin_value(&sr, "PHI1", PinValue::High, "TEST_CLOCK");
|
|
sr.update();
|
|
wait_for_pin_settlement();
|
|
|
|
// Verify reset cleared everything
|
|
let shift_reg_value = sr.get_shift_register();
|
|
println!("Shift register after reset: 0x{:03X}", shift_reg_value);
|
|
assert_eq!(shift_reg_value, 0, "Shift register should be 0 after reset");
|
|
|
|
// Clean up pin drivers
|
|
remove_pin_driver(&sr, "RESET");
|
|
remove_pin_driver(&sr, "PHI1");
|
|
remove_pin_driver(&sr, "PHI2");
|
|
|
|
println!("=== Intel 4003 Reset Functionality Test Complete ===");
|
|
}
|