tis_100/node/
stack.rs

1use super::Node;
2use io::IoBusView;
3use core::Port::*;
4
5/// A node which stores values written to it on a stack. When the node is read from it will pop the
6/// top value off of the stack and return it.
7#[derive(Debug)]
8pub struct StackMemoryNode {
9    stack: Vec<isize>,
10    read_index: Option<usize>,
11}
12
13impl StackMemoryNode {
14    /// Construct a new, empty `StackMemoryNode`.
15    pub fn new() -> StackMemoryNode {
16        StackMemoryNode {
17            stack: Vec::new(),
18            read_index: None,
19        }
20    }
21}
22
23impl Node for StackMemoryNode {
24    /// At the start of each cycle, the top value is made available on all ports. Any values that
25    /// have been written to this node are then added to the stack.
26    fn step(&mut self, io: &mut IoBusView) {
27        let dirs = vec![LEFT, RIGHT, UP, DOWN];
28
29        // Use last instead of pop so that the value is only removed if a node reads it.
30        if let Some(&val) = self.stack.last() {
31            self.read_index = Some(self.stack.len() - 1);
32            for &dir in dirs.iter() {
33                io.write(dir, val);
34            }
35        }
36
37        for &dir in dirs.iter() {
38            if let Some(val) = io.read(dir) {
39                self.stack.push(val);
40            }
41        }
42    }
43
44    // At the end of each cycle, check if the top value was actually read from and clear it from
45    // the stack if it was.
46    fn sync(&mut self, io: &mut IoBusView) {
47        if !io.is_blocked() {
48            if let Some(index) = self.read_index {
49                self.stack.remove(index);
50                self.read_index = None;
51            }
52        }
53    }
54}