vcd_ng/
lib.rs

1//! This crate reads and writes [VCD (Value Change Dump)][wp] files, a common format used with
2//! logic analyzers, HDL simulators, and other EDA tools.
3//!
4//! [wp]: https://en.wikipedia.org/wiki/Value_change_dump
5//!
6//! ## Example
7//!
8//! ```
9//! use std::io;
10//! use std::io::ErrorKind::InvalidInput;
11//! use vcd_ng::{ self, Value, TimescaleUnit, SimulationCommand };
12//!
13//! /// Write out a clocked signal to a VCD file
14//! fn write_clocked_vcd(shift_reg: u32, w: &mut impl io::Write) -> io::Result<()> {
15//!   let mut writer = vcd_ng::Writer::new(w);
16//!
17//!   // Write the header
18//!   writer.timescale(1, TimescaleUnit::US)?;
19//!   writer.add_module("top")?;
20//!   let clock = writer.add_wire(1, "clock")?;
21//!   let data = writer.add_wire(1, "data")?;
22//!   writer.upscope()?;
23//!   writer.enddefinitions()?;
24//!
25//!   // Write the initial values
26//!   writer.begin(SimulationCommand::Dumpvars)?;
27//!   writer.change_scalar(clock, Value::V0)?;
28//!   writer.change_scalar(data, Value::V0)?;
29//!   writer.end()?;
30//!
31//!   // Write the data values
32//!   let mut t = 0;
33//!   for i in 0..32 {
34//!     t += 4;
35//!     writer.timestamp(t)?;
36//!     writer.change_scalar(clock, Value::V1)?;
37//!     writer.change_scalar(data, ((shift_reg >> i) & 1) != 0)?;
38//!
39//!     t += 4;
40//!     writer.timestamp(t)?;
41//!     writer.change_scalar(clock, Value::V0)?;
42//!   }
43//!   Ok(())
44//! }
45//!
46//! /// Parse a VCD file containing a clocked signal and decode the signal
47//! fn read_clocked_vcd(r: &mut impl io::Read) -> io::Result<u32> {
48//!    let mut parser = vcd_ng::Parser::new(r);
49//!
50//!    // Parse the header and find the wires
51//!    let header = parser.parse_header()?;
52//!    let clock = header.find_var(&["top", "clock"])
53//!       .ok_or_else(|| io::Error::new(InvalidInput, "no wire top.clock"))?.code;
54//!    let data = header.find_var(&["top", "data"])
55//!       .ok_or_else(|| io::Error::new(InvalidInput, "no wire top.data"))?.code;
56//!
57//!    // Iterate through the remainder of the file and decode the data
58//!    let mut shift_reg = 0;
59//!    let mut data_val = Value::X;
60//!    let mut clock_val = Value::X;
61//!
62//!    for command_result in parser {
63//!      use vcd_ng::Command::*;
64//!      let command = command_result?;
65//!      match command {
66//!        ChangeScalar(i, v) if i == clock => {
67//!          if clock_val == Value::V1 && v == Value::V0 { // falling edge on clock
68//!             let shift_bit = match data_val { Value::V1 => (1 << 31), _ => 0 };
69//!             shift_reg = (shift_reg >> 1) | shift_bit;
70//!          }
71//!          clock_val = v;
72//!        }
73//!        ChangeScalar(i, v) if i == data => {
74//!          data_val = v;
75//!        }
76//!        _ => (),
77//!      }
78//!    }
79//!
80//!    Ok(shift_reg)
81//! }
82//!
83//! let mut buf = Vec::new();
84//! let data = 0xC0DE1234;
85//! write_clocked_vcd(data, &mut buf).expect("Failed to write");
86//! let value = read_clocked_vcd(&mut &buf[..]).expect("Failed to read");
87//! assert_eq!(value, data);
88//! ```
89
90use std::error::Error;
91use std::fmt::{self, Display};
92use std::io;
93use std::str::FromStr;
94use compact_str::CompactString;
95use bitvec::prelude::*;
96
97mod read;
98pub use read::Parser;
99
100mod write;
101pub use write::Writer;
102
103mod idcode;
104pub use idcode::IdCode;
105
106mod fastflow;
107pub use fastflow::{ FastFlow, FastFlowToken, FFValueChange };
108
109/// Error wrapping a static string message explaining why parsing failed.
110#[derive(Debug)]
111pub struct InvalidData(&'static str);
112impl Display for InvalidData {
113    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
114        self.0.fmt(f)
115    }
116}
117impl Error for InvalidData {
118    fn description(&self) -> &str {
119        self.0
120    }
121}
122impl From<InvalidData> for io::Error {
123    fn from(e: InvalidData) -> io::Error {
124        io::Error::new(io::ErrorKind::InvalidData, e.0)
125    }
126}
127
128/// A unit of time for the `$timescale` command.
129#[derive(Debug, Copy, Clone, Eq, PartialEq)]
130pub enum TimescaleUnit {
131    S,
132    MS,
133    US,
134    NS,
135    PS,
136    FS,
137}
138
139impl FromStr for TimescaleUnit {
140    type Err = InvalidData;
141    fn from_str(s: &str) -> Result<Self, Self::Err> {
142        use TimescaleUnit::*;
143        match s {
144            "s" => Ok(S),
145            "ms" => Ok(MS),
146            "us" => Ok(US),
147            "ns" => Ok(NS),
148            "ps" => Ok(PS),
149            "fs" => Ok(FS),
150            _ => Err(InvalidData("invalid timescale unit")),
151        }
152    }
153}
154
155impl Display for TimescaleUnit {
156    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
157        write!(
158            f,
159            "{}",
160            self.as_str()
161        )
162    }
163}
164
165impl TimescaleUnit {
166    pub fn divisor(&self) -> u64 {
167        use TimescaleUnit::*;
168        match *self {
169            S => 1,
170            MS => 1_000,
171            US => 1_000_000,
172            NS => 1_000_000_000,
173            PS => 1_000_000_000_000,
174            FS => 1_000_000_000_000_000,
175        }
176    }
177
178    pub fn fraction(&self) -> f64 {
179        1.0 / (self.divisor() as f64)
180    }
181
182    pub fn as_str(&self) -> &'static str {
183        use TimescaleUnit::*;
184        match *self {
185            S => "s",
186            MS => "ms",
187            US => "us",
188            NS => "ns",
189            PS => "ps",
190            FS => "fs"
191        }
192    }
193}
194
195/// A four-valued logic scalar value.
196#[derive(Debug, Copy, Clone, Eq, PartialEq)]
197pub enum Value {
198    /// Logic low (prefixed with `V` to make a valid Rust identifier)
199    V0 = 0,
200
201    /// Logic high (prefixed with `V` to make a valid Rust identifier)
202    V1 = 1,
203
204    /// An uninitialized or unknown value
205    X = 2,
206
207    /// The "high-impedance" value
208    Z = 3,
209}
210
211impl Value {
212    #[inline]
213    fn parse(v: u8) -> Result<Value, InvalidData> {
214        use Value::*;
215        match v {
216            b'0' => Ok(V0),
217            b'1' => Ok(V1),
218            b'x' | b'X' => Ok(X),
219            b'z' | b'Z' => Ok(Z),
220            _ => Err(InvalidData("invalid VCD value")),
221        }
222    }
223
224    #[inline]
225    fn from_01xz(is_01: bool, is_xz: bool) -> Value {
226        match (is_01, is_xz) {
227            (false, false) => Value::V0,
228            (true, false) => Value::V1,
229            (false, true) => Value::X,
230            (true, true) => Value::Z,
231        }
232    }
233
234    #[inline]
235    fn as_01xz(self) -> (bool, bool) {
236        let value = self as u8;
237        ((value & 1) != 0, (value >> 1 & 1) != 0)
238    }
239}
240
241impl FromStr for Value {
242    type Err = InvalidData;
243    fn from_str(s: &str) -> Result<Self, Self::Err> {
244        Value::parse(*s.as_bytes().get(0).unwrap_or(&b' '))
245    }
246}
247
248impl From<bool> for Value {
249    /// `true` converts to `V1`, `false` to `V0`
250    #[inline]
251    fn from(v: bool) -> Value {
252        if v {
253            Value::V1
254        } else {
255            Value::V0
256        }
257    }
258}
259
260impl Display for Value {
261    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
262        use Value::*;
263        write!(
264            f,
265            "{}",
266            match *self {
267                V0 => "0",
268                V1 => "1",
269                X => "x",
270                Z => "z",
271            }
272        )
273    }
274}
275
276/// A fixed box of [`Value`]s with bit compression. It is more efficient than `Vec<Value>`.
277#[derive(PartialEq, Clone)]
278pub struct VecValue {
279    is_01: BitVec,
280    is_xz: BitVec
281}
282
283/// An iterator over bits in a [`VecValue`].
284pub struct VecValueIter<'i> {
285    is_01_iter: bitvec::slice::BitValIter<'i, usize, Lsb0>,
286    is_xz_iter: bitvec::slice::BitValIter<'i, usize, Lsb0>
287}
288
289impl<'i> Iterator for VecValueIter<'i> {
290    type Item = Value;
291
292    #[inline]
293    fn next(&mut self) -> Option<Value> {
294        let is_01 = self.is_01_iter.next()?;
295        let is_xz = self.is_xz_iter.next()?;
296        Some(Value::from_01xz(is_01, is_xz))
297    }
298}
299
300impl<'i> IntoIterator for &'i VecValue {
301    type Item = Value;
302    type IntoIter = VecValueIter<'i>;
303
304    #[inline]
305    fn into_iter(self) -> VecValueIter<'i> {
306        // VecValueIter { i: 0, v: self }
307        VecValueIter {
308            is_01_iter: self.is_01.iter().by_vals(),
309            is_xz_iter: self.is_xz.iter().by_vals()
310        }
311    }
312}
313
314impl std::fmt::Debug for VecValue {
315    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
316        write!(f, "VecValue(")?;
317        for value in self {
318            write!(f, "{}", value)?;
319        }
320        write!(f, ")")
321    }
322}
323
324impl VecValue {
325    /// Create a new empty vector of values
326    #[inline]
327    pub fn new() -> VecValue {
328        VecValue {
329            is_01: BitVec::new(),
330            is_xz: BitVec::new()
331        }
332    }
333
334    /// Create a new vector with the same value repeated for `len` times.
335    #[inline]
336    pub fn repeat(value: Value, len: usize) -> VecValue {
337        let (is_01, is_xz) = value.as_01xz();
338        VecValue {
339            is_01: BitVec::repeat(is_01, len),
340            is_xz: BitVec::repeat(is_xz, len)
341        }
342    }
343
344    /// Get a bit from the vector
345    #[inline]
346    pub fn get_bit(&self, i: usize) -> Value {
347        Value::from_01xz(self.is_01[i], self.is_xz[i])
348    }
349
350    /// Set a bit in the vector
351    #[inline]
352    pub fn set_bit(&mut self, i: usize, value: Value) {
353        let (is_01, is_xz) = value.as_01xz();
354        self.is_01.set(i, is_01);
355        self.is_xz.set(i, is_xz);
356    }
357
358    /// Set a range of bits in the vector
359    #[inline]
360    pub fn set_bits(&mut self, start: usize, vvalue: &VecValue) {
361        let len = vvalue.len();
362        self.is_01[start..start + len].copy_from_bitslice(&vvalue.is_01);
363        self.is_xz[start..start + len].copy_from_bitslice(&vvalue.is_xz);
364    }
365
366    /// Get the bits that are different in the vector
367    #[inline]
368    pub fn difference(&self, start: usize, vvalue: &VecValue) -> BitVec {
369        let len = vvalue.len();
370        let mut x01 = vvalue.is_01.clone();
371        let mut xxz = vvalue.is_xz.clone();
372        x01 ^= &self.is_01[start..start + len];
373        xxz ^= &self.is_xz[start..start + len];
374        x01 |= &xxz;
375        x01
376    }
377
378    /// Get the length of the vector
379    #[inline]
380    pub fn len(&self) -> usize {
381        self.is_01.len()
382    }
383
384    /// Push a value to the tail of the vector.
385    #[inline]
386    pub fn push(&mut self, value: Value) {
387        let (is_01, is_xz) = value.as_01xz();
388        self.is_01.push(is_01);
389        self.is_xz.push(is_xz);
390    }
391
392    /// Get immutable iterator into bit content.
393    #[inline]
394    pub fn iter(&self) -> VecValueIter {
395        (&self).into_iter()
396    }
397}
398
399impl From<Vec<Value>> for VecValue {
400    fn from(vec: Vec<Value>) -> Self {
401        let mut ret = VecValue::new();
402        for v in vec {
403            ret.push(v);
404        }
405        ret
406    }
407}
408
409/// A type of scope, as used in the `$scope` command.
410#[derive(Debug, Copy, Clone, Eq, PartialEq)]
411#[non_exhaustive]
412pub enum ScopeType {
413    Module,
414    Task,
415    Function,
416    Begin,
417    Fork,
418}
419
420impl FromStr for ScopeType {
421    type Err = InvalidData;
422    fn from_str(s: &str) -> Result<Self, Self::Err> {
423        use ScopeType::*;
424        match s {
425            "module" => Ok(Module),
426            "task" => Ok(Task),
427            "function" => Ok(Function),
428            "begin" => Ok(Begin),
429            "fork" => Ok(Fork),
430            _ => Err(InvalidData("invalid scope type")),
431        }
432    }
433}
434
435impl Display for ScopeType {
436    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
437        use ScopeType::*;
438        write!(
439            f,
440            "{}",
441            match *self {
442                Module => "module",
443                Task => "task",
444                Function => "function",
445                Begin => "begin",
446                Fork => "fork",
447            }
448        )
449    }
450}
451
452/// A type of variable, as used in the `$var` command.
453#[derive(Debug, Copy, Clone, Eq, PartialEq)]
454#[non_exhaustive]
455pub enum VarType {
456    Event,
457    Integer,
458    Parameter,
459    Real,
460    Reg,
461    Supply0,
462    Supply1,
463    Time,
464    Tri,
465    TriAnd,
466    TriOr,
467    TriReg,
468    Tri0,
469    Tri1,
470    WAnd,
471    Wire,
472    WOr,
473    String,
474}
475
476impl FromStr for VarType {
477    type Err = InvalidData;
478    fn from_str(s: &str) -> Result<Self, Self::Err> {
479        use VarType::*;
480        match s {
481            "event" => Ok(Event),
482            "integer" => Ok(Integer),
483            "parameter" => Ok(Parameter),
484            "real" => Ok(Real),
485            "reg" => Ok(Reg),
486            "supply0" => Ok(Supply0),
487            "supply1" => Ok(Supply1),
488            "time" => Ok(Time),
489            "tri" => Ok(Tri),
490            "triand" => Ok(TriAnd),
491            "trior" => Ok(TriOr),
492            "trireg" => Ok(TriReg),
493            "tri0" => Ok(Tri0),
494            "tri1" => Ok(Tri1),
495            "wand" => Ok(WAnd),
496            "wire" => Ok(Wire),
497            "wor" => Ok(WOr),
498            "string" => Ok(String),
499            _ => Err(InvalidData("invalid variable type")),
500        }
501    }
502}
503
504impl Display for VarType {
505    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
506        use VarType::*;
507        write!(
508            f,
509            "{}",
510            match *self {
511                Event => "event",
512                Integer => "integer",
513                Parameter => "parameter",
514                Real => "real",
515                Reg => "reg",
516                Supply0 => "supply0",
517                Supply1 => "supply1",
518                Time => "time",
519                Tri => "tri",
520                TriAnd => "triand",
521                TriOr => "trior",
522                TriReg => "trireg",
523                Tri0 => "tri0",
524                Tri1 => "tri1",
525                WAnd => "wand",
526                Wire => "wire",
527                WOr => "wor",
528                String => "string",
529            }
530        )
531    }
532}
533
534/// Information on a VCD scope as represented by a `$scope` command and its children.
535#[derive(Debug, Clone, PartialEq)]
536pub struct Scope {
537    pub scope_type: ScopeType,
538    pub identifier: CompactString,
539    pub children: Vec<ScopeItem>,
540}
541
542impl Scope {
543    /// Looks up a variable by reference.
544    pub fn find_var<'a>(&'a self, reference: &str) -> Option<&'a Var> {
545        for c in &self.children {
546            if let &ScopeItem::Var(ref v) = c {
547                if v.reference == reference {
548                    return Some(v);
549                }
550            }
551        }
552        None
553    }
554}
555
556impl Default for Scope {
557    fn default() -> Scope {
558        Scope {
559            scope_type: ScopeType::Module,
560            identifier: "".into(),
561            children: Vec::new(),
562        }
563    }
564}
565
566/// Index of a VCD variable reference, either a bit select index `[i]` or a range index `[msb:lsb]`
567#[derive(Debug, Copy, Clone, PartialEq)]
568pub enum ReferenceIndex {
569    BitSelect(i32),
570    Range(i32, i32),
571}
572
573impl FromStr for ReferenceIndex {
574    type Err = std::io::Error;
575    fn from_str(s: &str) -> Result<Self, Self::Err> {
576        use std::io::{Error, ErrorKind};
577        use ReferenceIndex::*;
578        let s = s.trim_start_matches('[').trim_end_matches(']');
579        match s.find(':') {
580            Some(idx) => {
581                let msb: i32 = s[..idx]
582                    .trim()
583                    .parse()
584                    .map_err(|e| Error::new(ErrorKind::InvalidData, e))?;
585                let lsb: i32 = s[idx..]
586                    .trim_start_matches(':')
587                    .trim()
588                    .parse()
589                    .map_err(|e| Error::new(ErrorKind::InvalidData, e))?;
590                Ok(Range(msb, lsb))
591            }
592            None => {
593                let idx = s
594                    .trim()
595                    .parse()
596                    .map_err(|e| Error::new(ErrorKind::InvalidData, e))?;
597                Ok(BitSelect(idx))
598            }
599        }
600    }
601}
602
603impl Display for ReferenceIndex {
604    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
605        use ReferenceIndex::*;
606        match self {
607            BitSelect(idx) => write!(f, "[{}]", idx)?,
608            Range(msb, lsb) => write!(f, "[{}:{}]", msb, lsb)?,
609        };
610        Ok(())
611    }
612}
613
614/// Information on a VCD variable as represented by a `$var` command.
615#[derive(Debug, Clone, PartialEq)]
616pub struct Var {
617    pub var_type: VarType,
618    pub size: u32,
619    pub code: IdCode,
620    pub reference: CompactString,
621    pub index: Option<ReferenceIndex>,
622}
623
624/// An item in a scope -- either a child scope or a variable.
625#[derive(Debug, Clone, PartialEq)]
626pub enum ScopeItem {
627    Scope(Scope),
628    Var(Var),
629    Comment(CompactString),
630}
631
632/// An element in a VCD file.
633#[derive(Debug, PartialEq, Clone)]
634#[non_exhaustive]
635pub enum Command {
636    /// A `$comment` command
637    Comment(CompactString),
638
639    /// A `$date` command
640    Date(CompactString),
641
642    /// A `$version` command
643    Version(CompactString),
644
645    /// A `$timescale` command
646    Timescale(u32, TimescaleUnit),
647
648    /// A `$scope` command
649    ScopeDef(ScopeType, CompactString),
650
651    /// An `$upscope` command
652    Upscope,
653
654    /// A `$var` command
655    VarDef(VarType, u32, IdCode, CompactString, Option<ReferenceIndex>),
656
657    /// An `$enddefinitions` command
658    Enddefinitions,
659
660    /// A `#xxx` timestamp
661    Timestamp(u64),
662
663    /// A `0a` change to a scalar variable
664    ChangeScalar(IdCode, Value),
665
666    /// A `b0000 a` change to a vector variable
667    ChangeVector(IdCode, VecValue),
668
669    /// A `r1.234 a` change to a real variable
670    ChangeReal(IdCode, f64),
671
672    /// A `sSTART a` change to a (real?) variable
673    ChangeString(IdCode, CompactString),
674
675    /// A beginning of a simulation command. Unlike header commands, which are parsed atomically,
676    /// simulation commands emit a Begin, followed by the data changes within them, followed by
677    /// End.
678    Begin(SimulationCommand),
679
680    /// An end of a simulation command.
681    End(SimulationCommand),
682}
683
684/// A simulation command type, used in `Command::Begin` and `Command::End`.
685#[derive(Debug, Copy, Clone, Eq, PartialEq)]
686#[non_exhaustive]
687pub enum SimulationCommand {
688    Dumpall,
689    Dumpoff,
690    Dumpon,
691    Dumpvars,
692}
693
694impl Display for SimulationCommand {
695    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
696        use SimulationCommand::*;
697        write!(
698            f,
699            "{}",
700            match *self {
701                Dumpall => "dumpall",
702                Dumpoff => "dumpoff",
703                Dumpon => "dumpon",
704                Dumpvars => "dumpvars",
705            }
706        )
707    }
708}
709
710/// Structure containing the data from the header of a VCD file.
711#[derive(Debug, Default)]
712#[non_exhaustive]
713pub struct Header {
714    pub comment: Option<CompactString>,
715    pub date: Option<CompactString>,
716    pub version: Option<CompactString>,
717    pub timescale: Option<(u32, TimescaleUnit)>,
718    pub items: Vec<ScopeItem>,
719}
720
721impl Header {
722    /// Find the scope object at a specified path.
723    ///
724    /// ## Example
725    ///
726    /// ```rust
727    /// let mut parser = vcd_ng::Parser::new(&b"
728    /// $scope module a $end
729    /// $scope module b $end
730    /// $var integer 16 n0 counter $end
731    /// $upscope $end
732    /// $upscope $end
733    /// $enddefinitions $end
734    /// "[..]);
735    /// let header = parser.parse_header().unwrap();
736    /// let scope = header.find_scope(&["a", "b"]).unwrap();
737    /// assert_eq!(scope.identifier, "b");
738    /// ```
739    pub fn find_scope<S>(&self, path: &[S]) -> Option<&Scope>
740    where
741        S: std::borrow::Borrow<str>,
742    {
743        fn find_nested_scope<'a, S>(mut scope: &'a Scope, mut path: &[S]) -> Option<&'a Scope>
744        where
745            S: std::borrow::Borrow<str>,
746        {
747            'deeper: while !path.is_empty() {
748                for child in &scope.children {
749                    match child {
750                        ScopeItem::Scope(ref new_scope)
751                            if new_scope.identifier == path[0].borrow() =>
752                        {
753                            scope = new_scope;
754                            path = &path[1..];
755                            continue 'deeper;
756                        }
757                        _ => (),
758                    }
759                }
760                return None;
761            }
762            Some(scope)
763        }
764
765        if path.is_empty() {
766            return None;
767        }
768
769        let scope = self.items.iter().find(|item| match item {
770            ScopeItem::Scope(scope) => scope.identifier == path[0].borrow(),
771            _ => false,
772        });
773
774        if let Some(ScopeItem::Scope(scope)) = scope {
775            find_nested_scope(scope, &path[1..])
776        } else {
777            None
778        }
779    }
780
781    /// Find the variable object at a specified path.
782    ///
783    /// ## Example
784    ///
785    /// ```rust
786    /// let mut parser = vcd_ng::Parser::new(&b"
787    /// $scope module a $end
788    /// $scope module b $end
789    /// $var integer 16 n0 counter $end
790    /// $upscope $end
791    /// $upscope $end
792    /// $enddefinitions $end
793    /// "[..]);
794    /// let header = parser.parse_header().unwrap();
795    /// let var = header.find_var(&["a", "b", "counter"]).unwrap();
796    /// assert_eq!(var.reference, "counter");
797    /// ```
798    pub fn find_var<S>(&self, path: &[S]) -> Option<&Var>
799    where
800        S: std::borrow::Borrow<str>,
801    {
802        let scope = self.find_scope(&path[..path.len() - 1])?;
803        scope.find_var(path[path.len() - 1].borrow())
804    }
805}