1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
use super::*;
use std::io::Write;

#[derive(Debug)]
pub struct Terminal {
    name: String,
    chr: char,
    file: Option<std::fs::File>,
    out_valid: bool,
}

impl Terminal {
    pub fn new(name: String, filename: Option<&str>) -> Terminal {
        let file = if let Some(filename) = filename {
            Some(std::fs::File::create(filename).unwrap())
        } else {
            None
        };
        Terminal {
            name,
            chr: '\0',
            file,
            out_valid: false,
        }
    }

    fn print(&mut self) {
        if self.out_valid {
            let s = self.chr;
            if let Some(file) = &mut self.file {
                write!(file, "{s}").unwrap();
                file.flush().unwrap();
            } else {
                print!("{s}");
                std::io::stdout().flush().unwrap();
            }
        }
    }
}

impl Ext for Terminal {
    fn name(&self) -> String { self.name.clone() }
    fn instantiate(&mut self, _path: Path) {}
    fn incoming_ports(&self) -> Vec<PortName> { vec!["out_data".to_string(), "out_valid".to_string()] }
    fn outgoing_ports(&self) -> Vec<PortName> { vec![] }

    fn update(&mut self, _path: Path, port: &PortName, value: Value) -> Vec<(PortName, Value)> {
        if value.is_x() {
            return vec![];
        }
        if port == "out_valid" {
            self.out_valid = value.to_bool().unwrap();
        } else if port == "out_data" {
            if let Some(n) = value.to_u64() {
                if n < 256 {
                    if let Ok(k) = n.try_into() {
                        if let Some(ch) = char::from_u32(k) {
                            self.chr = ch;
                        }
                    }
                }
            }
        }
        vec![]
    }

    fn clock(&mut self, _path: Path) -> Vec<(PortName, Value)> {
        self.print();
        vec![]
    }

    fn reset(&mut self, _path: Path) -> Vec<(PortName, Value)> {
        self.print();
        vec![]
    }
}