Crate vcd

Source
Expand description

This crate reads and writes VCD (Value Change Dump) files, a common format used with logic analyzers, HDL simulators, and other EDA tools.

It provides:

§Example

use std::io;
use std::io::ErrorKind::InvalidInput;
use vcd::{ self, Value, TimescaleUnit, SimulationCommand };

/// Write out a clock and data signal to a VCD file
fn write_clocked_vcd(shift_reg: u32, w: &mut dyn io::Write) -> io::Result<()> {
  let mut writer = vcd::Writer::new(w);

  // Write the header
  writer.timescale(1, TimescaleUnit::US)?;
  writer.add_module("top")?;
  let clock = writer.add_wire(1, "clock")?;
  let data = writer.add_wire(1, "data")?;
  writer.upscope()?;
  writer.enddefinitions()?;

  // Write the initial values
  writer.begin(SimulationCommand::Dumpvars)?;
  writer.change_scalar(clock, Value::V0)?;
  writer.change_scalar(data, Value::V0)?;
  writer.end()?;

  // Write the data values
  let mut t = 0;
  for i in 0..32 {
    t += 4;
    writer.timestamp(t)?;
    writer.change_scalar(clock, Value::V1)?;
    writer.change_scalar(data, ((shift_reg >> i) & 1) != 0)?;

    t += 4;
    writer.timestamp(t)?;
    writer.change_scalar(clock, Value::V0)?;
  }
  Ok(())
}

/// Parse a VCD file containing a clocked signal and decode the signal
fn read_clocked_vcd(r: &mut dyn io::BufRead) -> io::Result<u32> {
   let mut parser = vcd::Parser::new(r);

   // Parse the header and find the wires
   let header = parser.parse_header()?;
   let clock = header.find_var(&["top", "clock"])
      .ok_or_else(|| io::Error::new(InvalidInput, "no wire top.clock"))?.code;
   let data = header.find_var(&["top", "data"])
      .ok_or_else(|| io::Error::new(InvalidInput, "no wire top.data"))?.code;

   // Iterate through the remainder of the file and decode the data
   let mut shift_reg = 0;
   let mut data_val = Value::X;
   let mut clock_val = Value::X;

   for command_result in parser {
     let command = command_result?;
     use vcd::Command::*;
     match command {
       ChangeScalar(i, v) if i == clock => {
         if clock_val == Value::V1 && v == Value::V0 { // falling edge on clock
            let shift_bit = match data_val { Value::V1 => (1 << 31), _ => 0 };
            shift_reg = (shift_reg >> 1) | shift_bit;
         }
         clock_val = v;
       }
       ChangeScalar(i, v) if i == data => {
         data_val = v;
       }
       _ => (),
     }
   }

   Ok(shift_reg)
}

let mut buf = Vec::new();
let data = 0xC0DE1234;
write_clocked_vcd(data, &mut buf).expect("Failed to write");
let value = read_clocked_vcd(&mut &buf[..]).expect("Failed to read");
assert_eq!(value, data);

Structs§

Header
Structure containing the data from the header of a VCD file.
IdCode
An ID used within the file to refer to a particular variable.
InvalidReferenceIndex
Parse error for invalid reference index.
InvalidScopeType
Parse error for invalid scope type.
InvalidTimescaleUnit
Parse error for invalid timescale unit.
InvalidValue
Parse error for invalid VCD logic value.
InvalidVarType
Parse error for invalid variable type.
ParseError
Error from parsing VCD
Parser
VCD parser.
Scope
Information on a VCD scope as represented by a $scope command and its children.
Var
Information on a VCD variable as represented by a $var command.
Vector
Vector of Value
VectorIter
Iterator for a Vector
Writer
Struct wrapping an std::io::Write with methods for writing VCD commands and data.

Enums§

Command
An element in a VCD file.
InvalidIdCode
Parse error for invalid ID code.
ParseErrorKind
Errors that can be encountered while parsing.
ReferenceIndex
Index of a VCD variable reference: either a bit select index [i] or a range index [msb:lsb]
ScopeItem
An item in a scope
ScopeType
A type of scope, as used in the $scope command.
SimulationCommand
A simulation command type, used in Command::Begin and Command::End.
TimescaleUnit
A unit of time for the $timescale command.
Value
A four-valued logic scalar value.
VarType
A type of variable, as used in the $var command.