feat(cpu): add A1/A2/A3 address cycle timing and fix pin propagation

This commit is contained in:
Jan-Peter von Hunnius 2026-02-24 18:58:14 +01:00
parent 3cdf99630c
commit 20884b57c3
17 changed files with 4165 additions and 270 deletions

View file

@ -70,6 +70,7 @@ pub struct Pin {
last_update: Instant,
settlement_time: Duration,
connected_pins: Vec<Arc<Mutex<Pin>>>,
is_propagating: bool,
}
impl Pin {
pub fn new(name: String) -> Self {
@ -80,6 +81,7 @@ impl Pin {
last_update: Instant::now(),
settlement_time: Duration::from_nanos(10), // 10ns settlement time
connected_pins: Vec::new(),
is_propagating: false,
}
}
@ -162,27 +164,45 @@ impl Pin {
&self.connected_pins
}
pub fn propagate(&self) {
for connected_pin in &self.connected_pins {
if let Ok(mut pin) = connected_pin.lock() {
// Copy our drivers to the connected pin (simulate electrical connection)
let mut new_drivers = self.drivers.clone();
pub fn propagate(&mut self) {
if self.is_propagating {
return;
}
// Merge with existing drivers on the connected pin
for (driver, value) in &pin.drivers {
new_drivers.insert(driver.clone(), *value);
}
self.is_propagating = true;
pin.drivers = new_drivers;
pin.last_update = Instant::now();
pin.recalculate_value();
// Use a scope guard to ensure the flag is reset even on panic
// This prevents the pin from becoming permanently unable to propagate
struct PropagationGuard<'a> {
flag: &'a mut bool,
}
impl<'a> Drop for PropagationGuard<'_> {
fn drop(&mut self) {
*self.flag = false;
}
}
let _guard = PropagationGuard {
flag: &mut self.is_propagating,
};
for connected_pin in &self.connected_pins {
if let Ok(mut pin) = connected_pin.lock() {
// Copy all our drivers with their strengths
for (driver_name, (value, strength)) in &self.drivers {
pin.set_driver_with_strength(Some(driver_name.clone()), *value, *strength);
}
}
}
// Guard will be dropped here, resetting is_propagating to false
}
fn recalculate_value(&mut self) {
if self.drivers.is_empty() {
self.settled_value = PinValue::HighZ;
self.last_update = Instant::now();
return;
}
@ -195,6 +215,7 @@ impl Pin {
}
if max_strength == DriveStrength::HighImpedance {
self.settled_value = PinValue::HighZ;
self.last_update = Instant::now();
return;
}
@ -215,6 +236,8 @@ impl Pin {
self.settled_value = PinValue::HighZ;
}
self.last_update = Instant::now();
// Propagate to connected pins
self.propagate();
}