8 个版本 (破坏性)
0.7.0 | 2023 年 7 月 15 日 |
---|---|
0.6.1 | 2020 年 9 月 12 日 |
0.6.0 | 2020 年 7 月 12 日 |
0.5.0 | 2019 年 10 月 3 日 |
0.1.0 | 2015 年 5 月 4 日 |
#1234 在 解析器实现
3,347 每月下载次数
在 40 个 包 (12 直接)
73KB
2K SLoC
VCD
此包读取和写入 VCD (值变化转储) 文件,这是一种常见的与逻辑分析仪、HDL 模拟器和其它 EDA 工具一起使用的格式。它提供了围绕 io::Read
和 io::Write
特性的流式包装,以读取和写入 VCD 命令和数据。
lib.rs
:
此包读取和写入 VCD (值变化转储) 文件,这是一种常见的与逻辑分析仪、HDL 模拟器和其它 EDA 工具一起使用的格式。
它提供了
Parser
包装std::io::BufRead
并提供了解析 VCDHeader
和Command
的能力。Writer
允许将 VCD 写入到std::io::Write
。- 表示VCD文件元素的几个结构和枚举,可以与
Parser
或Writer
一起使用,或者通过实现FromStr
和Display
接口单独使用。
示例
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);