Skip to content

Commit 7c5811c

Browse files
committed
Improve simulation algorithm
1 parent 0121111 commit 7c5811c

File tree

1 file changed

+120
-65
lines changed

1 file changed

+120
-65
lines changed

src/app.rs

Lines changed: 120 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -446,12 +446,15 @@ impl TemplateApp {
446446
// });
447447
ui.with_layout(Layout::left_to_right(Align::Min), |ui| {
448448
self.canvas_config = CanvasConfig::default();
449+
450+
let mut sorted_current: Vec<Pin> = self.current.iter().copied().collect();
451+
sorted_current.sort_by_key(|o| o.ins);
449452
egui::ScrollArea::vertical().show(ui, |ui| {
450453
ui.add_sized(
451454
vec2(200.0, 50.0),
452455
egui::TextEdit::multiline(&mut format!(
453456
"world {:#?}\n conn: {:#?}\n current: {:#?}\n moving: {:#?}\n\n\n",
454-
self.instances, self.connections, self.current, self.canvas_drag
457+
self.instances, self.connections, sorted_current, self.canvas_drag
455458
)),
456459
)
457460
});
@@ -665,11 +668,6 @@ impl TemplateApp {
665668
}
666669
}
667670
}
668-
log::info!(
669-
"drag: {}, resize: {}",
670-
self.canvas_drag.is_some(),
671-
self.resize.is_some()
672-
);
673671

674672
if self.canvas_drag.is_some() || self.resize.is_some() {
675673
// TODO: Only need to check this on placement and moving.
@@ -749,6 +747,7 @@ impl TemplateApp {
749747
connected_changed = true;
750748
self.connections.insert(*conn);
751749
}
750+
let old_len = self.connections.len();
752751
// Remove any connections not present in possible_connections
753752
self.connections.retain(|conn| {
754753
if possible_connections.contains(conn) {
@@ -758,6 +757,9 @@ impl TemplateApp {
758757
false
759758
}
760759
});
760+
if old_len != self.connections.len() {
761+
connected_changed = true;
762+
}
761763
}
762764
}
763765

@@ -812,46 +814,7 @@ impl TemplateApp {
812814
let mut current = HashSet::new();
813815
let mut seen = HashSet::new();
814816
for instance in &self.instances {
815-
let InstanceType::Power(p) = instance.ty else {
816-
continue;
817-
};
818-
if !p.on {
819-
continue;
820-
}
821-
self.flow_current(
822-
Pin {
823-
ins: instance.id,
824-
index: 0, // We know power instance pin is 0
825-
},
826-
&mut current,
827-
&mut seen,
828-
);
829-
}
830-
for instance in &self.instances {
831-
match instance.ty {
832-
InstanceType::Gate(_) => {
833-
let input1 = Pin {
834-
ins: instance.id,
835-
index: 0,
836-
};
837-
let input2 = Pin {
838-
ins: instance.id,
839-
index: 2,
840-
};
841-
let input1_p = current.contains(&input1);
842-
let input2_p = current.contains(&input2);
843-
844-
if input1_p && input2_p {
845-
let new_on = Pin {
846-
ins: instance.id,
847-
index: 1,
848-
};
849-
current.insert(new_on);
850-
self.flow_current(new_on, &mut current, &mut seen);
851-
}
852-
}
853-
InstanceType::Wire(_) | InstanceType::Power(_) => {}
854-
}
817+
self.determine_pins_state(*instance, &mut current, &mut seen);
855818
}
856819
self.current = current;
857820
}
@@ -980,34 +943,116 @@ impl TemplateApp {
980943
{
981944
self.resize = None;
982945
}
983-
// TODO: Remove from current table
946+
// TODO: Remove from current table. There is a panic
984947
}
985948

986-
fn flow_current(&self, pin: Pin, current: &mut HashSet<Pin>, seen: &mut HashSet<Pin>) {
987-
if seen.contains(&pin) {
988-
return;
949+
fn determine_pins_state(
950+
&self,
951+
instance: Instance,
952+
current: &mut HashSet<Pin>,
953+
seen: &mut HashSet<Pin>,
954+
) {
955+
match instance.ty {
956+
InstanceType::Gate(_) => {
957+
let input1 = Pin {
958+
ins: instance.id,
959+
index: 0,
960+
};
961+
let input2 = Pin {
962+
ins: instance.id,
963+
index: 2,
964+
};
965+
let input1_p = self.determine_pin(input1, current, seen);
966+
let input2_p = self.determine_pin(input2, current, seen);
967+
968+
if !(input1_p && input2_p) {
969+
let new_on = Pin {
970+
ins: instance.id,
971+
index: 1,
972+
};
973+
current.insert(new_on);
974+
}
975+
}
976+
InstanceType::Wire(_) => {
977+
let input1 = Pin {
978+
ins: instance.id,
979+
index: 0,
980+
};
981+
let input2 = Pin {
982+
ins: instance.id,
983+
index: 1,
984+
};
985+
let input_1_p = self.determine_pin(input1, current, seen);
986+
let input_2_p = self.determine_pin(input2, current, seen);
987+
if input_1_p || input_2_p {
988+
current.insert(input1);
989+
current.insert(input2);
990+
}
991+
}
992+
InstanceType::Power(p) => {
993+
let output = Pin {
994+
ins: instance.id,
995+
index: 0,
996+
};
997+
if p.on {
998+
current.insert(output);
999+
}
1000+
}
9891001
}
990-
seen.insert(pin);
991-
// TODO: Can do better search
992-
for connection in &self.connections {
993-
let Some((self_pin, other_pin)) = connection.get_pin_first(pin) else {
994-
continue;
995-
};
996-
current.insert(self_pin);
997-
current.insert(other_pin);
998-
// Also add current for other pins in the other_pin instance
999-
let instance = self.get_instance(other_pin.ins);
1000-
match instance.ty {
1001-
InstanceType::Gate(_) | InstanceType::Power(_) => {}
1002+
}
1003+
1004+
fn determine_pin(&self, pin: Pin, current: &mut HashSet<Pin>, seen: &mut HashSet<Pin>) -> bool {
1005+
if current.contains(&pin) {
1006+
return true;
1007+
}
1008+
let connected_pins = self.get_connected_pins(pin);
1009+
for connected_pin in connected_pins {
1010+
let other_instance = self.get_instance(connected_pin.ins);
1011+
match other_instance.ty {
1012+
InstanceType::Gate(_) => {
1013+
let output = Pin {
1014+
ins: other_instance.id,
1015+
index: 1,
1016+
};
1017+
if connected_pin == output {
1018+
self.determine_pins_state(*other_instance, current, seen);
1019+
if current.contains(&output) {
1020+
current.insert(pin);
1021+
return true;
1022+
}
1023+
}
1024+
}
10021025
InstanceType::Wire(_) => {
1003-
for pin in instance.pins() {
1026+
let start = Pin {
1027+
ins: other_instance.id,
1028+
index: 0,
1029+
};
1030+
let end = Pin {
1031+
ins: other_instance.id,
1032+
index: 1,
1033+
};
1034+
1035+
let res = if connected_pin == start {
1036+
self.determine_pin(end, current, seen)
1037+
} else if connected_pin == end {
1038+
self.determine_pin(start, current, seen)
1039+
} else {
1040+
unreachable!("Wire has two heads");
1041+
};
1042+
if res {
10041043
current.insert(pin);
1005-
self.flow_current(pin, current, seen);
1044+
return true;
1045+
}
1046+
}
1047+
InstanceType::Power(p) => {
1048+
if p.on {
1049+
current.insert(pin);
1050+
return true;
10061051
}
10071052
}
10081053
}
1009-
self.flow_current(other_pin, current, seen);
10101054
}
1055+
false
10111056
}
10121057
}
10131058

@@ -1133,6 +1178,16 @@ impl TemplateApp {
11331178
self.get_instance_mut(cid).mov(delta);
11341179
}
11351180
}
1181+
1182+
fn get_connected_pins(&self, pin: Pin) -> Vec<Pin> {
1183+
let mut res = Vec::new();
1184+
for conn in &self.connections {
1185+
if let Some((_, other)) = conn.get_pin_first(pin) {
1186+
res.push(other);
1187+
}
1188+
}
1189+
res
1190+
}
11361191
}
11371192

11381193
impl eframe::App for TemplateApp {

0 commit comments

Comments
 (0)