1use std::time::{Duration, Instant};
2
3use crate::{
4 chip::{Chip, PinId, PinType},
5 utilities::{Id, Storage},
6 State,
7};
8
9#[derive(Debug, Clone, Default)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub struct Board<C: Chip> {
12 chips: Storage<C>,
13 traces: Storage<Trace<C>>,
14}
15
16impl<C> Board<C>
17where
18 C: Chip,
19{
20 pub fn new() -> Self {
21 Board {
22 chips: Storage::default(),
23 traces: Storage::default(),
24 }
25 }
26
27 pub fn run(&mut self, tick_duration: Duration) {
28 for (_id, chip) in self.chips.as_mut_vec() {
29 let mut pins_to_reset = vec![];
30 for (pin_id, pin) in chip.list_pins() {
31 if matches!(pin.pin_type, PinType::Input) {
32 pins_to_reset.push(pin_id);
33 }
34 }
35 for pin_id in pins_to_reset {
36 if let Some(pin) = chip.get_pin_mut(pin_id) {
37 pin.state = State::Undefined
38 }
39 }
40 }
41
42 for (_id, trace) in self.traces.as_mut_vec() {
43 trace.calculate_state(&mut self.chips);
44 }
45
46 for (_id, chip) in self.chips.as_mut_vec() {
47 chip.run(tick_duration);
48 }
49 }
50
51 pub fn run_during(&mut self, duration: Duration, step: Duration) {
54 let mut elapsed = Duration::default();
55 while elapsed < duration {
56 self.run(step);
57 elapsed += step;
58 }
59 }
60
61 pub fn run_realtime(&mut self, duration: Duration) {
62 let instant = Instant::now();
63 let mut old = Instant::now();
64 let mut new = Instant::now();
65 while instant.elapsed() <= duration {
66 self.run(new.duration_since(old));
67 old = new;
68 new = Instant::now();
69 }
70 }
71
72 pub fn register_chip(&mut self, chip: C) -> Id<C> {
73 self.chips.add(chip)
74 }
75
76 pub fn register_trace(&mut self, trace: Trace<C>) -> Id<Trace<C>> {
77 self.traces.add(trace)
78 }
79
80 pub fn connect(
81 &mut self,
82 chip_a: Id<C>,
83 pin_a: PinId,
84 chip_b: Id<C>,
85 pin_b: PinId,
86 ) -> Id<Trace<C>> {
87 self.traces.add(Trace {
88 pins: vec![(chip_a, pin_a), (chip_b, pin_b)],
89 })
90 }
91
92 pub fn get_chip(&self, id: &Id<C>) -> Option<&C> {
93 self.chips.get(id)
94 }
95
96 pub fn get_chip_mut(&mut self, id: &Id<C>) -> Option<&mut C> {
97 self.chips.get_mut(id)
98 }
99
100 pub fn get_trace(&self, id: &Id<Trace<C>>) -> Option<&Trace<C>> {
101 self.traces.get(id)
102 }
103
104 pub fn get_trace_mut(&mut self, id: &Id<Trace<C>>) -> Option<&mut Trace<C>> {
105 self.traces.get_mut(id)
106 }
107}
108
109#[derive(Debug, Clone, Default)]
110#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
111#[cfg_attr(feature = "serde", serde(transparent))]
112pub struct Trace<C: Chip> {
113 pins: Vec<(Id<C>, usize)>,
114}
115
116impl<C> Trace<C>
117where
118 C: Chip,
119{
120 pub fn new() -> Self {
121 Trace { pins: Vec::new() }
122 }
123
124 pub fn connect(&mut self, chip: Id<C>, pin: PinId) {
125 if !self.pins.contains(&(chip, pin)) {
126 self.pins.push((chip, pin))
127 }
128 }
129
130 pub fn disconnect(&mut self, chip: Id<C>, pin: PinId) {
131 self.pins.retain(|&x| x != (chip, pin));
132 }
133
134 pub fn get_connections(&self) -> &[(Id<C>, usize)] {
135 &self.pins
136 }
137
138 pub fn calculate_state(&mut self, chip_storage: &mut Storage<C>) {
139 let mut base_state = State::Undefined;
140 for (chip_id, pin_id) in self.pins.iter() {
142 if let Some(pin) = chip_storage
143 .get(chip_id)
144 .and_then(|chip| chip.get_pin(*pin_id))
145 {
146 if matches!(pin.pin_type, PinType::Output) {
147 base_state = base_state.feed_state(pin.state);
148 }
149 }
150 }
151 for (chip_id, pin_id) in self.pins.iter() {
153 if let Some(mut pin) = chip_storage
154 .get_mut(chip_id)
155 .and_then(|chip| chip.get_pin_mut(*pin_id))
156 {
157 if matches!(pin.pin_type, PinType::Input) {
158 pin.state = pin.state.feed_state(base_state);
159 }
160 }
161 }
162 }
163}
164
165impl<C> From<Vec<(Id<C>, usize)>> for Trace<C>
166where
167 C: Chip,
168{
169 fn from(pins: Vec<(Id<C>, usize)>) -> Self {
170 Trace { pins }
171 }
172}