use std::error::Error;
use std::fmt::{self, Display};
use std::io;
use std::str::FromStr;
use compact_str::CompactString;
use bitvec::prelude::*;
mod read;
pub use read::Parser;
mod write;
pub use write::Writer;
mod idcode;
pub use idcode::IdCode;
mod fastflow;
pub use fastflow::{ FastFlow, FastFlowToken, FFValueChange };
#[derive(Debug)]
pub struct InvalidData(&'static str);
impl Display for InvalidData {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl Error for InvalidData {
fn description(&self) -> &str {
self.0
}
}
impl From<InvalidData> for io::Error {
fn from(e: InvalidData) -> io::Error {
io::Error::new(io::ErrorKind::InvalidData, e.0)
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum TimescaleUnit {
S,
MS,
US,
NS,
PS,
FS,
}
impl FromStr for TimescaleUnit {
type Err = InvalidData;
fn from_str(s: &str) -> Result<Self, Self::Err> {
use TimescaleUnit::*;
match s {
"s" => Ok(S),
"ms" => Ok(MS),
"us" => Ok(US),
"ns" => Ok(NS),
"ps" => Ok(PS),
"fs" => Ok(FS),
_ => Err(InvalidData("invalid timescale unit")),
}
}
}
impl Display for TimescaleUnit {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}",
self.as_str()
)
}
}
impl TimescaleUnit {
pub fn divisor(&self) -> u64 {
use TimescaleUnit::*;
match *self {
S => 1,
MS => 1_000,
US => 1_000_000,
NS => 1_000_000_000,
PS => 1_000_000_000_000,
FS => 1_000_000_000_000_000,
}
}
pub fn fraction(&self) -> f64 {
1.0 / (self.divisor() as f64)
}
pub fn as_str(&self) -> &'static str {
use TimescaleUnit::*;
match *self {
S => "s",
MS => "ms",
US => "us",
NS => "ns",
PS => "ps",
FS => "fs"
}
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Value {
V0 = 0,
V1 = 1,
X = 2,
Z = 3,
}
impl Value {
#[inline]
fn parse(v: u8) -> Result<Value, InvalidData> {
use Value::*;
match v {
b'0' => Ok(V0),
b'1' => Ok(V1),
b'x' | b'X' => Ok(X),
b'z' | b'Z' => Ok(Z),
_ => Err(InvalidData("invalid VCD value")),
}
}
#[inline]
fn from_01xz(is_01: bool, is_xz: bool) -> Value {
match (is_01, is_xz) {
(false, false) => Value::V0,
(true, false) => Value::V1,
(false, true) => Value::X,
(true, true) => Value::Z,
}
}
#[inline]
fn as_01xz(self) -> (bool, bool) {
let value = self as u8;
((value & 1) != 0, (value >> 1 & 1) != 0)
}
}
impl FromStr for Value {
type Err = InvalidData;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Value::parse(*s.as_bytes().get(0).unwrap_or(&b' '))
}
}
impl From<bool> for Value {
#[inline]
fn from(v: bool) -> Value {
if v {
Value::V1
} else {
Value::V0
}
}
}
impl Display for Value {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use Value::*;
write!(
f,
"{}",
match *self {
V0 => "0",
V1 => "1",
X => "x",
Z => "z",
}
)
}
}
#[derive(PartialEq, Clone)]
pub struct VecValue {
is_01: BitVec,
is_xz: BitVec
}
pub struct VecValueIter<'i> {
is_01_iter: bitvec::slice::BitValIter<'i, usize, Lsb0>,
is_xz_iter: bitvec::slice::BitValIter<'i, usize, Lsb0>
}
impl<'i> Iterator for VecValueIter<'i> {
type Item = Value;
#[inline]
fn next(&mut self) -> Option<Value> {
let is_01 = self.is_01_iter.next()?;
let is_xz = self.is_xz_iter.next()?;
Some(Value::from_01xz(is_01, is_xz))
}
}
impl<'i> IntoIterator for &'i VecValue {
type Item = Value;
type IntoIter = VecValueIter<'i>;
#[inline]
fn into_iter(self) -> VecValueIter<'i> {
VecValueIter {
is_01_iter: self.is_01.iter().by_vals(),
is_xz_iter: self.is_xz.iter().by_vals()
}
}
}
impl std::fmt::Debug for VecValue {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "VecValue(")?;
for value in self {
write!(f, "{}", value)?;
}
write!(f, ")")
}
}
impl VecValue {
#[inline]
pub fn new() -> VecValue {
VecValue {
is_01: BitVec::new(),
is_xz: BitVec::new()
}
}
#[inline]
pub fn repeat(value: Value, len: usize) -> VecValue {
let (is_01, is_xz) = value.as_01xz();
VecValue {
is_01: BitVec::repeat(is_01, len),
is_xz: BitVec::repeat(is_xz, len)
}
}
#[inline]
pub fn get_bit(&self, i: usize) -> Value {
Value::from_01xz(self.is_01[i], self.is_xz[i])
}
#[inline]
pub fn set_bit(&mut self, i: usize, value: Value) {
let (is_01, is_xz) = value.as_01xz();
self.is_01.set(i, is_01);
self.is_xz.set(i, is_xz);
}
#[inline]
pub fn set_bits(&mut self, start: usize, vvalue: &VecValue) {
let len = vvalue.len();
self.is_01[start..start + len].copy_from_bitslice(&vvalue.is_01);
self.is_xz[start..start + len].copy_from_bitslice(&vvalue.is_xz);
}
#[inline]
pub fn difference(&self, start: usize, vvalue: &VecValue) -> BitVec {
let len = vvalue.len();
let mut x01 = vvalue.is_01.clone();
let mut xxz = vvalue.is_xz.clone();
x01 ^= &self.is_01[start..start + len];
xxz ^= &self.is_xz[start..start + len];
x01 |= &xxz;
x01
}
#[inline]
pub fn len(&self) -> usize {
self.is_01.len()
}
#[inline]
pub fn push(&mut self, value: Value) {
let (is_01, is_xz) = value.as_01xz();
self.is_01.push(is_01);
self.is_xz.push(is_xz);
}
#[inline]
pub fn iter(&self) -> VecValueIter {
(&self).into_iter()
}
}
impl From<Vec<Value>> for VecValue {
fn from(vec: Vec<Value>) -> Self {
let mut ret = VecValue::new();
for v in vec {
ret.push(v);
}
ret
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[non_exhaustive]
pub enum ScopeType {
Module,
Task,
Function,
Begin,
Fork,
}
impl FromStr for ScopeType {
type Err = InvalidData;
fn from_str(s: &str) -> Result<Self, Self::Err> {
use ScopeType::*;
match s {
"module" => Ok(Module),
"task" => Ok(Task),
"function" => Ok(Function),
"begin" => Ok(Begin),
"fork" => Ok(Fork),
_ => Err(InvalidData("invalid scope type")),
}
}
}
impl Display for ScopeType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use ScopeType::*;
write!(
f,
"{}",
match *self {
Module => "module",
Task => "task",
Function => "function",
Begin => "begin",
Fork => "fork",
}
)
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[non_exhaustive]
pub enum VarType {
Event,
Integer,
Parameter,
Real,
Reg,
Supply0,
Supply1,
Time,
Tri,
TriAnd,
TriOr,
TriReg,
Tri0,
Tri1,
WAnd,
Wire,
WOr,
String,
}
impl FromStr for VarType {
type Err = InvalidData;
fn from_str(s: &str) -> Result<Self, Self::Err> {
use VarType::*;
match s {
"event" => Ok(Event),
"integer" => Ok(Integer),
"parameter" => Ok(Parameter),
"real" => Ok(Real),
"reg" => Ok(Reg),
"supply0" => Ok(Supply0),
"supply1" => Ok(Supply1),
"time" => Ok(Time),
"tri" => Ok(Tri),
"triand" => Ok(TriAnd),
"trior" => Ok(TriOr),
"trireg" => Ok(TriReg),
"tri0" => Ok(Tri0),
"tri1" => Ok(Tri1),
"wand" => Ok(WAnd),
"wire" => Ok(Wire),
"wor" => Ok(WOr),
"string" => Ok(String),
_ => Err(InvalidData("invalid variable type")),
}
}
}
impl Display for VarType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use VarType::*;
write!(
f,
"{}",
match *self {
Event => "event",
Integer => "integer",
Parameter => "parameter",
Real => "real",
Reg => "reg",
Supply0 => "supply0",
Supply1 => "supply1",
Time => "time",
Tri => "tri",
TriAnd => "triand",
TriOr => "trior",
TriReg => "trireg",
Tri0 => "tri0",
Tri1 => "tri1",
WAnd => "wand",
Wire => "wire",
WOr => "wor",
String => "string",
}
)
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Scope {
pub scope_type: ScopeType,
pub identifier: CompactString,
pub children: Vec<ScopeItem>,
}
impl Scope {
pub fn find_var<'a>(&'a self, reference: &str) -> Option<&'a Var> {
for c in &self.children {
if let &ScopeItem::Var(ref v) = c {
if v.reference == reference {
return Some(v);
}
}
}
None
}
}
impl Default for Scope {
fn default() -> Scope {
Scope {
scope_type: ScopeType::Module,
identifier: "".into(),
children: Vec::new(),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum ReferenceIndex {
BitSelect(i32),
Range(i32, i32),
}
impl FromStr for ReferenceIndex {
type Err = std::io::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
use std::io::{Error, ErrorKind};
use ReferenceIndex::*;
let s = s.trim_start_matches('[').trim_end_matches(']');
match s.find(':') {
Some(idx) => {
let msb: i32 = s[..idx]
.trim()
.parse()
.map_err(|e| Error::new(ErrorKind::InvalidData, e))?;
let lsb: i32 = s[idx..]
.trim_start_matches(':')
.trim()
.parse()
.map_err(|e| Error::new(ErrorKind::InvalidData, e))?;
Ok(Range(msb, lsb))
}
None => {
let idx = s
.trim()
.parse()
.map_err(|e| Error::new(ErrorKind::InvalidData, e))?;
Ok(BitSelect(idx))
}
}
}
}
impl Display for ReferenceIndex {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use ReferenceIndex::*;
match self {
BitSelect(idx) => write!(f, "[{}]", idx)?,
Range(msb, lsb) => write!(f, "[{}:{}]", msb, lsb)?,
};
Ok(())
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Var {
pub var_type: VarType,
pub size: u32,
pub code: IdCode,
pub reference: CompactString,
pub index: Option<ReferenceIndex>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum ScopeItem {
Scope(Scope),
Var(Var),
Comment(CompactString),
}
#[derive(Debug, PartialEq, Clone)]
#[non_exhaustive]
pub enum Command {
Comment(CompactString),
Date(CompactString),
Version(CompactString),
Timescale(u32, TimescaleUnit),
ScopeDef(ScopeType, CompactString),
Upscope,
VarDef(VarType, u32, IdCode, CompactString, Option<ReferenceIndex>),
Enddefinitions,
Timestamp(u64),
ChangeScalar(IdCode, Value),
ChangeVector(IdCode, VecValue),
ChangeReal(IdCode, f64),
ChangeString(IdCode, CompactString),
Begin(SimulationCommand),
End(SimulationCommand),
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[non_exhaustive]
pub enum SimulationCommand {
Dumpall,
Dumpoff,
Dumpon,
Dumpvars,
}
impl Display for SimulationCommand {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use SimulationCommand::*;
write!(
f,
"{}",
match *self {
Dumpall => "dumpall",
Dumpoff => "dumpoff",
Dumpon => "dumpon",
Dumpvars => "dumpvars",
}
)
}
}
#[derive(Debug, Default)]
#[non_exhaustive]
pub struct Header {
pub comment: Option<CompactString>,
pub date: Option<CompactString>,
pub version: Option<CompactString>,
pub timescale: Option<(u32, TimescaleUnit)>,
pub items: Vec<ScopeItem>,
}
impl Header {
pub fn find_scope<S>(&self, path: &[S]) -> Option<&Scope>
where
S: std::borrow::Borrow<str>,
{
fn find_nested_scope<'a, S>(mut scope: &'a Scope, mut path: &[S]) -> Option<&'a Scope>
where
S: std::borrow::Borrow<str>,
{
'deeper: while !path.is_empty() {
for child in &scope.children {
match child {
ScopeItem::Scope(ref new_scope)
if new_scope.identifier == path[0].borrow() =>
{
scope = new_scope;
path = &path[1..];
continue 'deeper;
}
_ => (),
}
}
return None;
}
Some(scope)
}
if path.is_empty() {
return None;
}
let scope = self.items.iter().find(|item| match item {
ScopeItem::Scope(scope) => scope.identifier == path[0].borrow(),
_ => false,
});
if let Some(ScopeItem::Scope(scope)) = scope {
find_nested_scope(scope, &path[1..])
} else {
None
}
}
pub fn find_var<S>(&self, path: &[S]) -> Option<&Var>
where
S: std::borrow::Borrow<str>,
{
let scope = self.find_scope(&path[..path.len() - 1])?;
scope.find_var(path[path.len() - 1].borrow())
}
}