1use std::io;
2
3use crate::{
4 Command, Header, IdCode, ReferenceIndex, Scope, ScopeItem, ScopeType, SimulationCommand,
5 TimescaleUnit, Value, Var, VarType,
6};
7
8pub struct Writer<W: io::Write> {
38 writer: W,
39 next_id_code: IdCode,
40 scope_depth: usize,
41}
42
43impl<W: io::Write> Writer<W> {
44 pub fn new(writer: W) -> Writer<W> {
51 Writer {
52 writer,
53 next_id_code: IdCode::FIRST,
54 scope_depth: 0,
55 }
56 }
57
58 pub fn writer(&mut self) -> &mut W {
60 &mut self.writer
61 }
62
63 pub fn flush(&mut self) -> io::Result<()> {
65 self.writer.flush()
66 }
67
68 pub fn header(&mut self, h: &Header) -> io::Result<()> {
70 if let Some(ref s) = h.date {
71 self.date(s)?;
72 }
73 if let Some(ref s) = h.version {
74 self.version(s)?;
75 }
76 if let Some((v, u)) = h.timescale {
77 self.timescale(v, u)?;
78 }
79 for i in &h.items {
80 match *i {
81 ScopeItem::Var(ref v) => self.var(v)?,
82 ScopeItem::Scope(ref s) => self.scope(s)?,
83 ScopeItem::Comment(ref c) => self.comment(c)?,
84 }
85 }
86 self.enddefinitions()
87 }
88
89 pub fn comment(&mut self, v: &str) -> io::Result<()> {
91 writeln!(self.writer, "$comment\n {}\n$end", v)
92 }
93
94 pub fn date(&mut self, v: &str) -> io::Result<()> {
96 writeln!(self.writer, "$date\n {}\n$end", v)
97 }
98
99 pub fn version(&mut self, v: &str) -> io::Result<()> {
101 writeln!(self.writer, "$version\n {}\n$end", v)
102 }
103
104 pub fn timescale(&mut self, ts: u32, unit: TimescaleUnit) -> io::Result<()> {
106 writeln!(self.writer, "$timescale {} {} $end", ts, unit)
107 }
108
109 pub fn scope_def(&mut self, t: ScopeType, i: &str) -> io::Result<()> {
111 self.scope_depth += 1;
112 writeln!(self.writer, "$scope {} {} $end", t, i)
113 }
114
115 pub fn add_module(&mut self, identifier: &str) -> io::Result<()> {
119 self.scope_def(ScopeType::Module, identifier)
120 }
121
122 pub fn upscope(&mut self) -> io::Result<()> {
124 debug_assert!(
125 self.scope_depth > 0,
126 "Generating invalid VCD: upscope without a matching scope"
127 );
128 self.scope_depth -= 1;
129 writeln!(self.writer, "$upscope $end")
130 }
131
132 pub fn scope(&mut self, s: &Scope) -> io::Result<()> {
135 self.scope_def(s.scope_type, &s.identifier[..])?;
136 for i in &s.items {
137 match *i {
138 ScopeItem::Var(ref v) => self.var(v)?,
139 ScopeItem::Scope(ref s) => self.scope(s)?,
140 ScopeItem::Comment(ref c) => self.comment(c)?,
141 }
142 }
143 self.upscope()
144 }
145
146 pub fn var_def(
148 &mut self,
149 var_type: VarType,
150 width: u32,
151 id: IdCode,
152 reference: &str,
153 index: Option<ReferenceIndex>,
154 ) -> io::Result<()> {
155 debug_assert!(
156 self.scope_depth > 0,
157 "Generating invalid VCD: variable must be in a scope"
158 );
159 if id >= self.next_id_code {
160 self.next_id_code = id.next();
161 }
162 match index {
163 Some(idx) => writeln!(
164 self.writer,
165 "$var {} {} {} {} {} $end",
166 var_type, width, id, reference, idx
167 ),
168 None => writeln!(
169 self.writer,
170 "$var {} {} {} {} $end",
171 var_type, width, id, reference
172 ),
173 }
174 }
175
176 pub fn add_var(
180 &mut self,
181 var_type: VarType,
182 width: u32,
183 reference: &str,
184 index: Option<ReferenceIndex>,
185 ) -> io::Result<IdCode> {
186 let id = self.next_id_code;
187 self.var_def(var_type, width, id, reference, index)?;
188 Ok(id)
189 }
190
191 pub fn add_wire(&mut self, width: u32, reference: &str) -> io::Result<IdCode> {
195 self.add_var(VarType::Wire, width, reference, None)
196 }
197
198 pub fn var(&mut self, v: &Var) -> io::Result<()> {
200 self.var_def(v.var_type, v.size, v.code, &v.reference[..], v.index)
201 }
202
203 pub fn enddefinitions(&mut self) -> io::Result<()> {
205 debug_assert!(
206 self.scope_depth == 0,
207 "Generating invalid VCD: {} scopes must be closed with $upscope before $enddefinitions",
208 self.scope_depth
209 );
210 writeln!(self.writer, "$enddefinitions $end")
211 }
212
213 pub fn timestamp(&mut self, ts: u64) -> io::Result<()> {
215 writeln!(self.writer, "#{}", ts)
216 }
217
218 pub fn change_scalar<V: Into<Value>>(&mut self, id: IdCode, v: V) -> io::Result<()> {
220 writeln!(self.writer, "{}{}", v.into(), id)
221 }
222
223 pub fn change_vector(&mut self, id: IdCode, v: impl IntoIterator<Item=Value>) -> io::Result<()> {
225 write!(self.writer, "b")?;
226 for i in v {
227 write!(self.writer, "{}", i)?
228 }
229 writeln!(self.writer, " {}", id)
230 }
231
232 pub fn change_real(&mut self, id: IdCode, v: f64) -> io::Result<()> {
234 writeln!(self.writer, "r{} {}", v, id)
235 }
236
237 pub fn change_string(&mut self, id: IdCode, v: &str) -> io::Result<()> {
239 writeln!(self.writer, "s{} {}", v, id)
240 }
241
242 pub fn begin(&mut self, c: SimulationCommand) -> io::Result<()> {
244 writeln!(self.writer, "${}", c)
245 }
246
247 pub fn end(&mut self) -> io::Result<()> {
249 writeln!(self.writer, "$end")
250 }
251
252 pub fn command(&mut self, c: &Command) -> io::Result<()> {
254 use Command::*;
255 match *c {
256 Comment(ref c) => self.comment(&c[..]),
257 Date(ref c) => self.date(&c[..]),
258 Version(ref c) => self.version(&c[..]),
259 Timescale(v, u) => self.timescale(v, u),
260 ScopeDef(t, ref i) => self.scope_def(t, &i[..]),
261 Upscope => self.upscope(),
262 VarDef(t, s, i, ref r, idx) => self.var_def(t, s, i, &r[..], idx),
263 Enddefinitions => self.enddefinitions(),
264 Timestamp(t) => self.timestamp(t),
265 ChangeScalar(i, v) => self.change_scalar(i, v),
266 ChangeVector(i, ref v) => self.change_vector(i, v),
267 ChangeReal(i, v) => self.change_real(i, v),
268 ChangeString(i, ref v) => self.change_string(i, v),
269 Begin(c) => self.begin(c),
270 End(_) => self.end(),
271 }
272 }
273}