From 909cca250839a291e5ff3a640ac3a01c4707541c Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Sun, 7 Jan 2024 11:54:40 +0100 Subject: [PATCH] Initial SystemVerilog/fst2vcd support --- examples/vcd.rs | 2 +- src/lib.rs | 2 +- src/vcd/parse/scopes.rs | 62 ++++++++++++++++++++--------------------- src/vcd/signal.rs | 28 +++++++++++++++++-- tests/files.rs | 3 +- 5 files changed, 61 insertions(+), 36 deletions(-) diff --git a/examples/vcd.rs b/examples/vcd.rs index eb6b660..9f41299 100644 --- a/examples/vcd.rs +++ b/examples/vcd.rs @@ -73,7 +73,7 @@ fn main() -> std::io::Result<()> { let timestamps = vec![31499_000u32, 31500_000u32, 57760_000u32]; for timestamp in timestamps { let time = num::BigUint::from(timestamp); - let val = state_signal.query_string_val_on_tmln(&time, &vcd).unwrap(); + let val = state_signal.query_val_on_tmln(&time, &vcd).unwrap(); println!("Signal `{name}` has value `{val}` at time `{time}`"); } diff --git a/src/lib.rs b/src/lib.rs index 6bdb055..ab95da2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,7 +5,7 @@ mod vcd; pub use vcd::parse::parse_vcd; -pub use vcd::signal::{Signal, SignalType, SignalValue, SignalErrors}; +pub use vcd::signal::{Signal, SignalErrors, SignalType, SignalValue}; pub use vcd::types::{Metadata, Timescale, Version}; pub use vcd::types::{ScopeIdx, SignalIdx, VCD}; diff --git a/src/vcd/parse/scopes.rs b/src/vcd/parse/scopes.rs index 5fe106b..a5fc587 100644 --- a/src/vcd/parse/scopes.rs +++ b/src/vcd/parse/scopes.rs @@ -42,6 +42,16 @@ pub(super) fn parse_var( "wand", "wire", "wor", + "int", + "int_s", + "shortint", + "int_l", + "longint", + "char", + "byte", + "logic", + "bit", + "shortreal", ]; // $var parameter 3 a IDLE $end @@ -66,6 +76,15 @@ pub(super) fn parse_var( "wand" => Ok(SignalType::WAnd), "wire" => Ok(SignalType::Wire), "wor" => Ok(SignalType::WOr), + "int" => Ok(SignalType::SVInt), + "int_s" => Ok(SignalType::SVShortInt), + "shortint" => Ok(SignalType::SVShortInt), + "int_l" => Ok(SignalType::SVLongInt), + "longint" => Ok(SignalType::SVLongInt), + "logic" => Ok(SignalType::SVLogic), + "shortreal" => Ok(SignalType::SVShortReal), + "byte" => Ok(SignalType::SVChar), + "char" => Ok(SignalType::SVChar), _ => { let err = format!( "Error near {}:{} \ @@ -84,38 +103,19 @@ pub(super) fn parse_var( // $var parameter 3 a IDLE $end // ^ - num_bits - let num_bits = match var_type { - SignalType::Event - | SignalType::Integer - | SignalType::Parameter - | SignalType::Reg - | SignalType::Supply0 - | SignalType::Supply1 - | SignalType::Tri - | SignalType::TriAnd - | SignalType::TriOr - | SignalType::TriReg - | SignalType::Tri0 - | SignalType::Tri1 - | SignalType::Time - | SignalType::WAnd - | SignalType::Wire - | SignalType::WOr => { - let num_bits = word - .parse::() - .unwrap_or_else(|_| panic!("{}", parse_err)); - let num_bits = u32::try_from(num_bits).map_err(|_| { - format!( - "Error near {}:{} while parsing vcd file at {cursor:?}. \ + let num_bits = { + let num_bits = word + .parse::() + .unwrap_or_else(|_| panic!("{}", parse_err)); + let num_bits = u32::try_from(num_bits).map_err(|_| { + format!( + "Error near {}:{} while parsing vcd file at {cursor:?}. \ This signal has {num_bits} > 2^32 - 1 bits.", - file!(), - line!() - ) - })?; - Some(num_bits) - } - // for strings, reals, and realtimes we don't really care what the number of bits is - _ => None, + file!(), + line!() + ) + })?; + Some(num_bits) }; // $var parameter 3 a IDLE $end diff --git a/src/vcd/signal.rs b/src/vcd/signal.rs index b87e1a2..23954a0 100644 --- a/src/vcd/signal.rs +++ b/src/vcd/signal.rs @@ -1,3 +1,5 @@ +use std::fmt; + // Copyright (C) 2022 Yehowshua Immanuel // This program is distributed under both the GPLV3 license // and the YEHOWSHUA license, both of which can be found at @@ -32,6 +34,13 @@ pub enum SignalType { WAnd, Wire, WOr, + SVLogic, + SVInt, + SVShortInt, + SVLongInt, + SVChar, + SVBit, + SVShortReal, } #[derive(Debug, PartialEq)] @@ -40,11 +49,26 @@ pub enum SignalValue { String(String), } +impl fmt::Display for SignalValue { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + SignalValue::BigUint(num) => { write!(f, "BigUnit: {num}") } + SignalValue::String(val) => {write!(f, "String: {val}")} + } + } +} + pub struct QueryResult { pub current: Option<(TimeStamp, T)>, pub next: Option, } +impl fmt::Display for QueryResult { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "(current: {:?}, next: {:?})", self.current, self.next) + } +} + pub struct Signal<'a>(pub(super) &'a SignalEnum); impl<'a> Signal<'a> { @@ -465,7 +489,7 @@ impl SignalEnum { if lsb_indxs_of_string_tmstmp_vals_on_tmln.is_empty() { return Ok(QueryResult { current: None, - next: None + next: None, }); } @@ -610,7 +634,7 @@ impl SignalEnum { if lsb_indxs_of_num_tmstmp_vals_on_tmln.is_empty() { return Ok(QueryResult { current: None, - next: None + next: None, }); } diff --git a/tests/files.rs b/tests/files.rs index 38c08b2..a5b9af2 100644 --- a/tests/files.rs +++ b/tests/files.rs @@ -5,8 +5,9 @@ // TODO: we should eventually be able to only test on just // the files const -pub const FILES: [&str; 31] = [ +pub const FILES: [&str; 32] = [ "./tests/vcd-files/aldec/SPI_Write.vcd", + "./tests/vcd-files/fst2vcd/logic.vcd", "./tests/vcd-files/ghdl/alu.vcd", "./tests/vcd-files/ghdl/idea.vcd", "./tests/vcd-files/ghdl/pcpu.vcd",