use std::str::FromStr;
use std::fmt::{self, Display};
use std::error::Error;
use std::io;
mod read;
pub use read::Parser;
mod write;
pub use write::Writer;
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum TimescaleUnit {
S, MS, US, NS, PS, FS,
}
#[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) }
}
impl FromStr for TimescaleUnit {
type Err = InvalidData;
fn from_str(s: &str) -> Result<Self, Self::Err> {
use self::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 self::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 self::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)]
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 self::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 self::ScopeType::*;
write!(f, "{}", match *self {
Module => "module",
Task => "task",
Function => "function",
Begin => "begin",
Fork => "fork",
})
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum VarType {
Event,
Integer,
Parameter,
Real,
Reg,
Supply0,
Supply1,
Time,
Tri,
TriAnd,
TriOr,
TriReg,
Tri0,
Tri1,
WAnd,
Wire,
WOr,
}
impl FromStr for VarType {
type Err = InvalidData;
fn from_str(s: &str) -> Result<Self, Self::Err> {
use self::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),
_ => Err(InvalidData("invalid variable type"))
}
}
}
impl Display for VarType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::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",
})
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
pub struct IdCode(u64);
const ID_CHAR_MIN: u8 = b'!';
const ID_CHAR_MAX: u8 = b'~';
const NUM_ID_CHARS: u64 = (ID_CHAR_MAX - ID_CHAR_MIN + 1) as u64;
impl IdCode {
fn new(v: &[u8]) -> Result<IdCode, InvalidData> {
if v.is_empty() { return Err(InvalidData("ID cannot be empty")) }
let mut result = 0u64;
for &i in v.iter().rev() {
if i < ID_CHAR_MIN || i > ID_CHAR_MAX { return Err(InvalidData("invalid characters in ID")) }
let c = ((i - ID_CHAR_MIN) as u64) + 1;
result = result.checked_mul(NUM_ID_CHARS).and_then(|x| x.checked_add(c))
.ok_or(InvalidData("ID too long"))?;
}
Ok(IdCode(result - 1))
}
pub const FIRST: IdCode = IdCode(0);
pub fn next(&self) -> IdCode {
IdCode(self.0 + 1)
}
}
impl FromStr for IdCode {
type Err = InvalidData;
fn from_str(s: &str) -> Result<Self, Self::Err> {
IdCode::new(s.as_bytes())
}
}
impl From<u32> for IdCode {
fn from(i: u32) -> IdCode { IdCode(i as u64) }
}
impl From<u64> for IdCode {
fn from(i: u64) -> IdCode { IdCode(i) }
}
impl Display for IdCode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut i = self.0;
loop {
let r = i % NUM_ID_CHARS;
try!(write!(f, "{}", (r as u8 + ID_CHAR_MIN) as char));
if i < NUM_ID_CHARS { break; }
i = i / NUM_ID_CHARS - 1;
}
Ok(())
}
}
#[test]
fn test_id_code() {
let mut id = IdCode::FIRST;
for i in 0..10000 {
println!("{} {}", i, id);
assert_eq!(id.to_string().parse::<IdCode>().unwrap(), id);
id = id.next();
}
assert_eq!("!".parse::<IdCode>().unwrap().to_string(), "!");
assert_eq!("!!!!!!!!!!".parse::<IdCode>().unwrap().to_string(), "!!!!!!!!!!");
assert_eq!("~".parse::<IdCode>().unwrap().to_string(), "~");
assert_eq!("~~~~~~~~~".parse::<IdCode>().unwrap().to_string(), "~~~~~~~~~");
assert_eq!("n999999999".parse::<IdCode>().unwrap().to_string(), "n999999999");
assert!("n9999999999".parse::<IdCode>().is_err());
}
#[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> {
let s = s.trim_start_matches('[').trim_end_matches(']');
use ReferenceIndex::*;
use io::{Error, ErrorKind};
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)]
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)]
pub enum SimulationCommand {
Dumpall,
Dumpoff,
Dumpon,
Dumpvars,
}
impl Display for SimulationCommand {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::SimulationCommand::*;
write!(f, "{}", match *self {
Dumpall => "dumpall",
Dumpoff => "dumpoff",
Dumpon => "dumpon",
Dumpvars => "dumpvars",
})
}
}
#[derive(Debug, Default)]
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())
}
}