vcd_ng/
write.rs

1use std::io;
2
3use crate::{
4    Command, Header, IdCode, ReferenceIndex, Scope, ScopeItem, ScopeType, SimulationCommand,
5    TimescaleUnit, Value, VecValue, Var, VarType,
6};
7
8/// Struct wrapping an `io::Write` with methods for writing VCD commands and data.
9pub struct Writer<W: io::Write> {
10    writer: W,
11    next_id_code: IdCode,
12    scope_depth: usize,
13}
14
15impl<W: io::Write> Writer<W> {
16    /// Creates a Writer, wrapping an io::Write.
17    ///
18    /// ```
19    /// let mut buf = Vec::new();
20    /// let mut vcd = vcd_ng::Writer::new(&mut buf);
21    /// ```
22    pub fn new(writer: W) -> Writer<W> {
23        Writer {
24            writer,
25            next_id_code: IdCode::FIRST,
26            scope_depth: 0,
27        }
28    }
29
30    /// Writes a complete header with the fields from a `Header` struct from the parser.
31    pub fn header(&mut self, h: &Header) -> io::Result<()> {
32        if let Some(ref s) = h.date {
33            self.date(s)?;
34        }
35        if let Some(ref s) = h.version {
36            self.version(s)?;
37        }
38        if let Some(ref s) = h.comment {
39            self.comment(s)?;
40        }
41        if let Some((v, u)) = h.timescale {
42            self.timescale(v, u)?;
43        }
44        for i in &h.items {
45            match *i {
46                ScopeItem::Var(ref v) => self.var(v)?,
47                ScopeItem::Scope(ref s) => self.scope(s)?,
48                ScopeItem::Comment(ref c) => self.comment(c)?,
49            }
50        }
51        self.enddefinitions()
52    }
53
54    /// Writes a `$comment` command.
55    pub fn comment(&mut self, v: &str) -> io::Result<()> {
56        writeln!(self.writer, "$comment\n    {}\n$end", v)
57    }
58
59    /// Writes a `$date` command.
60    pub fn date(&mut self, v: &str) -> io::Result<()> {
61        writeln!(self.writer, "$date\n    {}\n$end", v)
62    }
63
64    /// Writes a `$version` command.
65    pub fn version(&mut self, v: &str) -> io::Result<()> {
66        writeln!(self.writer, "$version\n    {}\n$end", v)
67    }
68
69    /// Writes a `$timescale` command.
70    pub fn timescale(&mut self, ts: u32, unit: TimescaleUnit) -> io::Result<()> {
71        writeln!(self.writer, "$timescale {} {} $end", ts, unit)
72    }
73
74    /// Writes a `$scope` command.
75    pub fn scope_def(&mut self, t: ScopeType, i: &str) -> io::Result<()> {
76        self.scope_depth += 1;
77        writeln!(self.writer, "$scope {} {} $end", t, i)
78    }
79
80    /// Writes a `$scope` command for a module.
81    ///
82    /// Convenience wrapper around `scope_def`.
83    pub fn add_module(&mut self, identifier: &str) -> io::Result<()> {
84        self.scope_def(ScopeType::Module, identifier)
85    }
86
87    /// Writes an `$upscope` command.
88    pub fn upscope(&mut self) -> io::Result<()> {
89        debug_assert!(
90            self.scope_depth > 0,
91            "Generating invalid VCD: upscope without a matching scope"
92        );
93        self.scope_depth -= 1;
94        writeln!(self.writer, "$upscope $end")
95    }
96
97    /// Writes a `$scope` command, a series of `$var` commands, and an `$upscope` commands from
98    /// a `Scope` structure from the parser.
99    pub fn scope(&mut self, s: &Scope) -> io::Result<()> {
100        self.scope_def(s.scope_type, &s.identifier[..])?;
101        for i in &s.children {
102            match *i {
103                ScopeItem::Var(ref v) => self.var(v)?,
104                ScopeItem::Scope(ref s) => self.scope(s)?,
105                ScopeItem::Comment(ref c) => self.comment(c)?,
106            }
107        }
108        self.upscope()
109    }
110
111    /// Writes a `$var` command with a specified id.
112    pub fn var_def(
113        &mut self,
114        var_type: VarType,
115        width: u32,
116        id: IdCode,
117        reference: &str,
118        index: Option<ReferenceIndex>,
119    ) -> io::Result<()> {
120        debug_assert!(
121            self.scope_depth > 0,
122            "Generating invalid VCD: variable must be in a scope"
123        );
124        if id >= self.next_id_code {
125            self.next_id_code = id.next();
126        }
127        match index {
128            Some(idx) => writeln!(
129                self.writer,
130                "$var {} {} {} {} {} $end",
131                var_type, width, id, reference, idx
132            ),
133            None => writeln!(
134                self.writer,
135                "$var {} {} {} {} $end",
136                var_type, width, id, reference
137            ),
138        }
139    }
140
141    /// Writes a `$var` command with the next available ID, returning the assigned ID.
142    ///
143    /// Convenience wrapper around `var_def`.
144    pub fn add_var(
145        &mut self,
146        var_type: VarType,
147        width: u32,
148        reference: &str,
149        index: Option<ReferenceIndex>,
150    ) -> io::Result<IdCode> {
151        let id = self.next_id_code;
152        self.var_def(var_type, width, id, reference, index)?;
153        Ok(id)
154    }
155
156    /// Adds a `$var` for a wire with the next available ID, returning the assigned ID.
157    ///
158    /// Convenience wrapper around `add_var`.
159    pub fn add_wire(&mut self, width: u32, reference: &str) -> io::Result<IdCode> {
160        self.add_var(VarType::Wire, width, reference, None)
161    }
162
163    /// Writes a `$var` command from a `Var` structure from the parser.
164    pub fn var(&mut self, v: &Var) -> io::Result<()> {
165        self.var_def(v.var_type, v.size, v.code, &v.reference[..], v.index)
166    }
167
168    /// Writes a `$enddefinitions` command to end the header.
169    pub fn enddefinitions(&mut self) -> io::Result<()> {
170        debug_assert!(
171            self.scope_depth == 0,
172            "Generating invalid VCD: {} scopes must be closed with $upscope before $enddefinitions",
173            self.scope_depth
174        );
175        writeln!(self.writer, "$enddefinitions $end")
176    }
177
178    /// Writes a `#xxx` timestamp.
179    pub fn timestamp(&mut self, ts: u64) -> io::Result<()> {
180        writeln!(self.writer, "#{}", ts)
181    }
182
183    /// Writes a change to a scalar variable.
184    pub fn change_scalar<V: Into<Value>>(&mut self, id: IdCode, v: V) -> io::Result<()> {
185        writeln!(self.writer, "{}{}", v.into(), id)
186    }
187
188    /// Writes a change to a vector variable.
189    pub fn change_vector(&mut self, id: IdCode, v: &VecValue) -> io::Result<()> {
190        write!(self.writer, "b")?;
191        for i in v {
192            write!(self.writer, "{}", i)?
193        }
194        writeln!(self.writer, " {}", id)
195    }
196
197    /// Writes a change to a real variable.
198    pub fn change_real(&mut self, id: IdCode, v: f64) -> io::Result<()> {
199        writeln!(self.writer, "r{} {}", v, id)
200    }
201
202    /// Writes a change to a string variable.
203    pub fn change_string(&mut self, id: IdCode, v: &str) -> io::Result<()> {
204        writeln!(self.writer, "s{} {}", v, id)
205    }
206
207    /// Writes the beginning of a simulation command.
208    pub fn begin(&mut self, c: SimulationCommand) -> io::Result<()> {
209        writeln!(self.writer, "${}", c)
210    }
211
212    /// Writes an `$end` to end a simulation command.
213    pub fn end(&mut self) -> io::Result<()> {
214        writeln!(self.writer, "$end")
215    }
216
217    /// Writes a command from a `Command` enum as parsed by the parser.
218    pub fn command(&mut self, c: &Command) -> io::Result<()> {
219        use Command::*;
220        match *c {
221            Comment(ref c) => self.comment(&c[..]),
222            Date(ref c) => self.date(&c[..]),
223            Version(ref c) => self.version(&c[..]),
224            Timescale(v, u) => self.timescale(v, u),
225            ScopeDef(t, ref i) => self.scope_def(t, &i[..]),
226            Upscope => self.upscope(),
227            VarDef(t, s, i, ref r, idx) => self.var_def(t, s, i, &r[..], idx),
228            Enddefinitions => self.enddefinitions(),
229            Timestamp(t) => self.timestamp(t),
230            ChangeScalar(i, v) => self.change_scalar(i, v),
231            ChangeVector(i, ref v) => self.change_vector(i, v),
232            ChangeReal(i, v) => self.change_real(i, v),
233            ChangeString(i, ref v) => self.change_string(i, v),
234            Begin(c) => self.begin(c),
235            End(_) => self.end(),
236        }
237    }
238}