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

@ -1,6 +1,7 @@
use parking_lot::Mutex;
use std::any::Any;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use std::sync::Arc;
use std::thread;
use std::time::{Duration, Instant};
@ -382,10 +383,9 @@ impl Intel4001 {
for i in 0..4 {
if let Ok(pin) = self.base.get_pin(&format!("IO{}", 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;
}
}
}
@ -499,9 +499,8 @@ impl Intel4001 {
fn tri_state_io_pins(&self) {
for i in 0..4 {
if let Ok(pin) = self.base.get_pin(&format!("IO{}", i)) {
if let Ok(mut pin_guard) = pin.lock() {
pin_guard.set_driver(Some(self.base.name()), PinValue::HighZ);
}
let mut pin_guard = pin.lock();
pin_guard.set_driver(Some(self.base.name()), PinValue::HighZ);
}
}
}
@ -575,11 +574,8 @@ impl Intel4001 {
/// Hardware: CI pin distinguishes I/O vs ROM access when chip selected (CM=1)
fn read_ci_pin(&self) -> bool {
if let Ok(pin) = self.base.get_pin("CI") {
if let Ok(pin_guard) = pin.lock() {
pin_guard.read() == PinValue::High
} else {
false
}
let pin_guard = pin.lock();
pin_guard.read() == PinValue::High
} else {
false
}
@ -620,22 +616,21 @@ impl Intel4001 {
fn update_io_pins(&self) {
for i in 0..4 {
if let Ok(pin) = self.base.get_pin(&format!("IO{}", i)) {
if let Ok(mut pin_guard) = pin.lock() {
match self.io_direction[i] {
IoDirection::Output => {
// Drive pin with output port value
let bit_value = (self.io_ports[i]) & 1;
let pin_value = if bit_value == 1 {
PinValue::High
} else {
PinValue::Low
};
pin_guard.set_driver(Some(self.base.name()), pin_value);
}
IoDirection::Input => {
// Input mode - tri-state pin
pin_guard.set_driver(Some(self.base.name()), PinValue::HighZ);
}
let mut pin_guard = pin.lock();
match self.io_direction[i] {
IoDirection::Output => {
// Drive pin with output port value
let bit_value = (self.io_ports[i]) & 1;
let pin_value = if bit_value == 1 {
PinValue::High
} else {
PinValue::Low
};
pin_guard.set_driver(Some(self.base.name()), pin_value);
}
IoDirection::Input => {
// Input mode - tri-state pin
pin_guard.set_driver(Some(self.base.name()), PinValue::HighZ);
}
}
}
@ -926,9 +921,17 @@ impl Component for Intel4001 {
self.base.is_running()
}
fn set_running(&mut self, running: bool) {
self.base.set_running(running);
}
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
}
impl RunnableComponent for Intel4001 {}
@ -1159,15 +1162,15 @@ mod tests {
// Initialize PHI1 to Low first
{
let mut phi1_guard = phi1_pin.lock().unwrap();
let mut phi1_guard = phi1_pin.lock();
phi1_guard.set_driver(Some("TEST".to_string()), PinValue::Low);
}
// Set up memory read operation: SYNC=1, CM=1, CI=0 (memory access)
{
let mut sync_guard = sync_pin.lock().unwrap();
let mut cm_guard = cm_pin.lock().unwrap();
let mut ci_guard = ci_pin.lock().unwrap();
let mut sync_guard = sync_pin.lock();
let mut cm_guard = cm_pin.lock();
let mut ci_guard = ci_pin.lock();
sync_guard.set_driver(Some("TEST".to_string()), PinValue::High);
cm_guard.set_driver(Some("TEST".to_string()), PinValue::High);
ci_guard.set_driver(Some("TEST".to_string()), PinValue::Low); // Memory access
@ -1175,7 +1178,7 @@ mod tests {
// Set Φ1 high (creating rising edge)
{
let mut phi1_guard = phi1_pin.lock().unwrap();
let mut phi1_guard = phi1_pin.lock();
phi1_guard.set_driver(Some("TEST".to_string()), PinValue::High);
}
@ -1224,9 +1227,9 @@ mod tests {
// Set up memory read operation: SYNC=1, chip_select=1, io_select=0 (memory access)
{
let mut sync_guard = sync_pin.lock().unwrap();
let mut cm_guard = cm_pin.lock().unwrap();
let mut ci_guard = ci_pin.lock().unwrap();
let mut sync_guard = sync_pin.lock();
let mut cm_guard = cm_pin.lock();
let mut ci_guard = ci_pin.lock();
sync_guard.set_driver(Some("TEST".to_string()), PinValue::High);
cm_guard.set_driver(Some("TEST".to_string()), PinValue::High);
ci_guard.set_driver(Some("TEST".to_string()), PinValue::Low); // Memory access, not I/O
@ -1259,9 +1262,9 @@ mod tests {
// Set memory operation active
{
let mut sync_guard = sync_pin.lock().unwrap();
let mut cm_guard = cm_pin.lock().unwrap();
let mut ci_guard = ci_pin.lock().unwrap();
let mut sync_guard = sync_pin.lock();
let mut cm_guard = cm_pin.lock();
let mut ci_guard = ci_pin.lock();
sync_guard.set_driver(Some("TEST".to_string()), PinValue::High);
cm_guard.set_driver(Some("TEST".to_string()), PinValue::High);
ci_guard.set_driver(Some("TEST".to_string()), PinValue::Low); // Memory access, not I/O
@ -1272,7 +1275,7 @@ mod tests {
// Now assert RESET
{
let mut reset_guard = reset_pin.lock().unwrap();
let mut reset_guard = reset_pin.lock();
reset_guard.set_driver(Some("TEST".to_string()), PinValue::High);
}
@ -1290,10 +1293,10 @@ mod tests {
let d3_pin = rom.get_pin("D3").unwrap();
// After reset, all pins should be HighZ (tri-stated)
assert_eq!(d0_pin.lock().unwrap().read(), PinValue::HighZ);
assert_eq!(d1_pin.lock().unwrap().read(), PinValue::HighZ);
assert_eq!(d2_pin.lock().unwrap().read(), PinValue::HighZ);
assert_eq!(d3_pin.lock().unwrap().read(), PinValue::HighZ);
assert_eq!(d0_pin.lock().read(), PinValue::HighZ);
assert_eq!(d1_pin.lock().read(), PinValue::HighZ);
assert_eq!(d2_pin.lock().read(), PinValue::HighZ);
assert_eq!(d3_pin.lock().read(), PinValue::HighZ);
}
#[test]
@ -1310,19 +1313,19 @@ mod tests {
let d3_pin = rom.get_pin("D3").unwrap();
// Initially, no operation - should be tri-stated
assert_eq!(d0_pin.lock().unwrap().read(), PinValue::HighZ);
assert_eq!(d1_pin.lock().unwrap().read(), PinValue::HighZ);
assert_eq!(d2_pin.lock().unwrap().read(), PinValue::HighZ);
assert_eq!(d3_pin.lock().unwrap().read(), PinValue::HighZ);
assert_eq!(d0_pin.lock().read(), PinValue::HighZ);
assert_eq!(d1_pin.lock().read(), PinValue::HighZ);
assert_eq!(d2_pin.lock().read(), PinValue::HighZ);
assert_eq!(d3_pin.lock().read(), PinValue::HighZ);
// Set up memory operation but don't complete address phase
let sync_pin = rom.get_pin("SYNC").unwrap();
let cm_pin = rom.get_pin("CM").unwrap();
let ci_pin = rom.get_pin("CI").unwrap();
let mut sync_guard = sync_pin.lock().unwrap();
let mut cm_guard = cm_pin.lock().unwrap();
let mut ci_guard = ci_pin.lock().unwrap();
let mut sync_guard = sync_pin.lock();
let mut cm_guard = cm_pin.lock();
let mut ci_guard = ci_pin.lock();
sync_guard.set_driver(Some("TEST".to_string()), PinValue::High);
cm_guard.set_driver(Some("TEST".to_string()), PinValue::High);
ci_guard.set_driver(Some("TEST".to_string()), PinValue::Low); // Memory access, not I/O
@ -1331,20 +1334,20 @@ mod tests {
rom.update();
// Should still be tri-stated during address phase
assert_eq!(d0_pin.lock().unwrap().read(), PinValue::HighZ);
assert_eq!(d1_pin.lock().unwrap().read(), PinValue::HighZ);
assert_eq!(d2_pin.lock().unwrap().read(), PinValue::HighZ);
assert_eq!(d3_pin.lock().unwrap().read(), PinValue::HighZ);
assert_eq!(d0_pin.lock().read(), PinValue::HighZ);
assert_eq!(d1_pin.lock().read(), PinValue::HighZ);
assert_eq!(d2_pin.lock().read(), PinValue::HighZ);
assert_eq!(d3_pin.lock().read(), PinValue::HighZ);
// Complete address phase but don't wait for latency
// Should still be tri-stated
rom.update();
// Should still be tri-stated (waiting for latency)
assert_eq!(d0_pin.lock().unwrap().read(), PinValue::HighZ);
assert_eq!(d1_pin.lock().unwrap().read(), PinValue::HighZ);
assert_eq!(d2_pin.lock().unwrap().read(), PinValue::HighZ);
assert_eq!(d3_pin.lock().unwrap().read(), PinValue::HighZ);
assert_eq!(d0_pin.lock().read(), PinValue::HighZ);
assert_eq!(d1_pin.lock().read(), PinValue::HighZ);
assert_eq!(d2_pin.lock().read(), PinValue::HighZ);
assert_eq!(d3_pin.lock().read(), PinValue::HighZ);
}
#[test]