virt_ic/
board.rs

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    /// Run the circuit for a certain amount of time segmented by a step
52    /// The smaller the step the more accurate the simulation will be.
53    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        // read state
141        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        // write state
152        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}