feat(cpu): add A1/A2/A3 address cycle timing and fix pin propagation
This commit is contained in:
parent
3cdf99630c
commit
20884b57c3
17 changed files with 4165 additions and 270 deletions
47
src/pin.rs
47
src/pin.rs
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue