feat: migrate to parking_lot mutex and add system control architecture

This commit is contained in:
Jan-Peter von Hunnius 2026-02-28 18:27:27 +01:00
parent 14060e15e5
commit 54144d10e9
29 changed files with 2387 additions and 1130 deletions

View file

@ -3,7 +3,8 @@
//! This test verifies that the Intel 4004 CPU state machine progresses correctly
//! through all phases: Idle → AddressPhase → WaitLatency → DriveData → Idle
use std::sync::{Arc, Mutex};
use parking_lot::Mutex;
use std::sync::Arc;
use std::thread;
use std::time::{Duration, Instant};
@ -46,16 +47,8 @@ impl CpuTestHelper {
let phi2 = Arc::new(Mutex::new(Pin::new("PHI2".to_string())));
// Connect CPU to test clock
cpu.get_pin("PHI1")
.unwrap()
.lock()
.unwrap()
.connect_to(phi1.clone());
cpu.get_pin("PHI2")
.unwrap()
.lock()
.unwrap()
.connect_to(phi2.clone());
cpu.get_pin("PHI1").unwrap().lock().connect_to(phi1.clone());
cpu.get_pin("PHI2").unwrap().lock().connect_to(phi2.clone());
CpuTestHelper {
cpu,
@ -90,11 +83,9 @@ impl CpuTestHelper {
// Phase 1: Φ1 high, Φ2 low
self.phi1
.lock()
.unwrap()
.set_driver(Some("clock".to_string()), PinValue::High);
self.phi2
.lock()
.unwrap()
.set_driver(Some("clock".to_string()), PinValue::Low);
thread::sleep(Duration::from_millis(1));
@ -104,11 +95,9 @@ impl CpuTestHelper {
// Phase 2: Φ1 low, Φ2 high
self.phi1
.lock()
.unwrap()
.set_driver(Some("clock".to_string()), PinValue::Low);
self.phi2
.lock()
.unwrap()
.set_driver(Some("clock".to_string()), PinValue::High);
thread::sleep(Duration::from_millis(1));
@ -117,11 +106,9 @@ impl CpuTestHelper {
// Phase 3: Both low
self.phi1
.lock()
.unwrap()
.set_driver(Some("clock".to_string()), PinValue::Low);
self.phi2
.lock()
.unwrap()
.set_driver(Some("clock".to_string()), PinValue::Low);
thread::sleep(Duration::from_millis(1));
@ -137,28 +124,18 @@ impl CpuTestHelper {
}
fn set_control_pins(&self, sync: bool, cm: bool, reset: bool) {
self.cpu
.get_pin("SYNC")
.unwrap()
.lock()
.unwrap()
.set_driver(
Some("test".to_string()),
if sync { PinValue::High } else { PinValue::Low },
);
self.cpu.get_pin("CM").unwrap().lock().unwrap().set_driver(
self.cpu.get_pin("SYNC").unwrap().lock().set_driver(
Some("test".to_string()),
if sync { PinValue::High } else { PinValue::Low },
);
self.cpu.get_pin("CM").unwrap().lock().set_driver(
Some("test".to_string()),
if cm { PinValue::High } else { PinValue::Low },
);
self.cpu
.get_pin("RESET")
.unwrap()
.lock()
.unwrap()
.set_driver(
Some("test".to_string()),
if reset { PinValue::High } else { PinValue::Low },
);
self.cpu.get_pin("RESET").unwrap().lock().set_driver(
Some("test".to_string()),
if reset { PinValue::High } else { PinValue::Low },
);
}
fn drive_data_bus(&self, data: u8) {
@ -168,7 +145,6 @@ impl CpuTestHelper {
.get_pin(&format!("D{}", i))
.unwrap()
.lock()
.unwrap()
.set_driver(
Some("test".to_string()),
if bit_value == 1 {
@ -184,10 +160,9 @@ impl CpuTestHelper {
let mut data = 0;
for i in 0..4 {
if let Ok(pin) = self.cpu.get_pin(&format!("D{}", i)) {
if let Ok(pin_guard) = pin.lock() {
if pin_guard.read() == PinValue::High {
data |= 1 << i;
}
let pin_guard = pin.lock();
if pin_guard.read() == PinValue::High {
data |= 1 << i;
}
}
}
@ -197,9 +172,8 @@ impl CpuTestHelper {
fn tri_state_data_bus(&self) {
for i in 0..4 {
if let Ok(pin) = self.cpu.get_pin(&format!("D{}", i)) {
if let Ok(mut pin_guard) = pin.lock() {
pin_guard.set_driver(Some("test".to_string()), PinValue::HighZ);
}
let mut pin_guard = pin.lock();
pin_guard.set_driver(Some("test".to_string()), PinValue::HighZ);
}
}
}
@ -294,7 +268,7 @@ fn test_intel_4004_state_machine_progression() {
for i in 0..4 {
let pin_name = format!("D{}", i);
if let Ok(pin) = helper.cpu.get_pin(&pin_name) {
let mut pin_guard = pin.lock().unwrap();
let mut pin_guard = pin.lock();
pin_guard.set_driver(Some("test".to_string()), PinValue::High);
}
}
@ -352,7 +326,6 @@ fn test_intel_4004_reset_functionality() {
.get_pin("RESET")
.unwrap()
.lock()
.unwrap()
.set_driver(Some("test".to_string()), PinValue::High);
helper.cpu.update();
@ -362,7 +335,6 @@ fn test_intel_4004_reset_functionality() {
.get_pin("RESET")
.unwrap()
.lock()
.unwrap()
.set_driver(Some("test".to_string()), PinValue::Low);
// Process the reset signal for multiple cycles to ensure it's applied
@ -378,7 +350,6 @@ fn test_intel_4004_reset_functionality() {
.get_pin("RESET")
.unwrap()
.lock()
.unwrap()
.set_driver(Some("test".to_string()), PinValue::High);
helper.cpu.update();
thread::sleep(Duration::from_millis(1));