use std::error::Error;
use std::fmt::{self, Display};
use std::io;
use std::str::FromStr;
mod read;
pub use read::Parser;
mod write;
pub use write::Writer;
mod idcode;
pub use idcode::IdCode;
#[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 {
use TimescaleUnit::*;
write!(
f,
"{}",
match *self {
S => "s",
MS => "ms",
US => "us",
NS => "ns",
PS => "ps",
FS => "fs",
}
)
}
}
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)
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Value {
V0,
V1,
X,
Z,
}
impl Value {
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")),
}
}
}
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 {
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(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: String,
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: "".to_string(),
children: Vec::new(),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum ReferenceIndex {
BitSelect(u32),
Range(u32, u32),
}
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: u32 = s[..idx]
.trim()
.parse()
.map_err(|e| Error::new(ErrorKind::InvalidData, e))?;
let lsb: u32 = 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: String,
pub index: Option<ReferenceIndex>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum ScopeItem {
Scope(Scope),
Var(Var),
}
#[derive(Debug, PartialEq, Clone)]
#[non_exhaustive]
pub enum Command {
Comment(String),
Date(String),
Version(String),
Timescale(u32, TimescaleUnit),
ScopeDef(ScopeType, String),
Upscope,
VarDef(VarType, u32, IdCode, String, Option<ReferenceIndex>),
Enddefinitions,
Timestamp(u64),
ChangeScalar(IdCode, Value),
ChangeVector(IdCode, Vec<Value>),
ChangeReal(IdCode, f64),
ChangeString(IdCode, String),
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<String>,
pub date: Option<String>,
pub version: Option<String>,
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())
}
}