From 6abcd7ce32ba57696f4204dc6e175fc39d36c0ab Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Tue, 25 Oct 2022 21:09:19 -0400 Subject: [PATCH 1/5] fix some errors/typos and prep for refactoring --- examples/vcd.rs | 18 +++++++++++++---- src/vcd/parse/events.rs | 8 -------- src/vcd/signal.rs | 13 +----------- src/vcd/types.rs | 45 ++++++++++++++--------------------------- 4 files changed, 30 insertions(+), 54 deletions(-) diff --git a/examples/vcd.rs b/examples/vcd.rs index 3b67482..af552bd 100644 --- a/examples/vcd.rs +++ b/examples/vcd.rs @@ -6,8 +6,6 @@ use std::fs::File; use fastwave_backend::*; -use num::{BigUint}; - fn indented_print(indent : u8, name : &String) { for _ in 0..indent {print!(" |");} print!("---"); @@ -19,7 +17,15 @@ fn print_root_scope_tree(root_idx: ScopeIdx, vcd: &VCD, indent : u8) { } else { for child_scope_idx in vcd.child_scopes_by_idx(root_idx) { indented_print(indent, vcd.scope_name_by_idx(child_scope_idx)); - let ScopeIdx(idx) = child_scope_idx; + // for signal_idx in vcd.get_children_signal_idxs(child_scope_idx) { + // let signal = vcd.try_signal_idx_to_signal(signal_idx).unwrap(); + // match signal { + // Signal::Data {..} => {} + // Signal::Alias {..} => {} + // } + // // let to_print = format!("{},{}", signal.name(), ) + // } + // vcd.try_signal_idx_to_signal(idx) print_root_scope_tree(child_scope_idx, vcd.clone(), indent + 1); } } @@ -47,7 +53,11 @@ fn main() -> std::io::Result<()> { ui_all_scopes(&vcd); - // let state_signal = vcd. + let file_path = "tests/vcd-files/amaranth/up_counter.vcd"; + let file = File::open(file_path)?; + let vcd = parse_vcd(file).unwrap(); + // let state_signal = vcd.all_si + // for signal_idx in vcd.si // let name = state_signal.name(); // let time = BigUint::from(57760000u32); // let val = state_signal diff --git a/src/vcd/parse/events.rs b/src/vcd/parse/events.rs index f1c7964..8475b4f 100644 --- a/src/vcd/parse/events.rs +++ b/src/vcd/parse/events.rs @@ -2,7 +2,6 @@ // This program is distributed under both the GPLV3 license // and the YEHOWSHUA license, both of which can be found at // the root of the folder containing the sources for this program. -use num::Zero; use super::*; @@ -13,7 +12,6 @@ pub(super) fn parse_events<'a>( ) -> Result<(), String> { let mut curr_tmstmp_lsb_idx = 0u32; let mut curr_tmstmp_len_u8 = 0u8; - let mut curr_time = BigUint::zero(); loop { let next_word = word_reader.next_word(); @@ -42,7 +40,6 @@ pub(super) fn parse_events<'a>( "Error near {f}:{l}. Failed to parse {value} as BigInt at {cursor:?}" ) })?; - curr_time = value.clone(); let mut value = value.to_bytes_le(); // TODO : u32 helps with less memory, but should ideally likely be // configurable. @@ -422,7 +419,6 @@ pub(super) fn parse_events<'a>( ref mut signal_error, num_bits, string_vals, - byte_len_of_num_tmstmp_vals_on_tmln, byte_len_of_string_tmstmp_vals_on_tmln, lsb_indxs_of_string_tmstmp_vals_on_tmln, .. @@ -497,12 +493,8 @@ pub(super) fn parse_events<'a>( match signal { Signal::Data { - name, - sig_type, ref mut signal_error, - num_bits, string_vals, - byte_len_of_num_tmstmp_vals_on_tmln, byte_len_of_string_tmstmp_vals_on_tmln, lsb_indxs_of_string_tmstmp_vals_on_tmln, .. diff --git a/src/vcd/signal.rs b/src/vcd/signal.rs index 2531255..c32be24 100644 --- a/src/vcd/signal.rs +++ b/src/vcd/signal.rs @@ -28,6 +28,7 @@ pub(super) enum TimelineQueryResults { String(String), } + #[derive(Debug)] pub enum Signal { Data { @@ -100,18 +101,6 @@ type SignalValNum = BigUint; // getter functions impl Signal { - pub fn self_idx(&self) -> Result { - match self { - Signal::Data { self_idx, ..} => {return Ok(self_idx.clone())}, - Signal::Alias { .. } => Err(format!( - "Error near {}:{}. A signal alias shouldn't \ - point to a signal alias.", - file!(), - line!() - )), - } - } - pub fn name(&self) -> String { match self { Signal::Data { name, ..} => name, diff --git a/src/vcd/types.rs b/src/vcd/types.rs index 1213874..ad56c3b 100644 --- a/src/vcd/types.rs +++ b/src/vcd/types.rs @@ -72,6 +72,11 @@ impl VCD { let scope = &self.all_scopes[idx]; scope.child_scopes.clone() } + pub fn get_children_signal_idxs(&self, scope_idx: ScopeIdx) -> Vec { + let ScopeIdx(idx) = scope_idx; + let scope = &self.all_scopes[idx]; + scope.child_signals.clone() + } pub fn scope_name_by_idx(&self, scope_idx: ScopeIdx) -> &String { let ScopeIdx(idx) = scope_idx; let scope = &self.all_scopes[idx]; @@ -109,40 +114,20 @@ impl VCD { )), } } - pub(super) fn dealiasing_signal_idx_to_signal_lookup<'a>( - &'a self, - idx: &SignalIdx, - ) -> Result<&'a Signal, String> { - // get the signal pointed to be SignalIdx from the arena - let SignalIdx(idx) = idx; - let signal = &self.all_signals[*idx]; - - // dereference signal if Signal::Alias, or keep idx if Signal::Data - let signal_idx = match signal { - Signal::Data { self_idx, .. } => *self_idx, - Signal::Alias { name, signal_alias } => *signal_alias, - }; - - // Should now point to Signal::Data variant, or else there's an error - let SignalIdx(idx) = signal_idx; - let signal = self.all_signals.get(idx).unwrap(); - match signal { - Signal::Data { .. } => Ok(signal), - Signal::Alias { .. } => Err(format!( - "Error near {}:{}. A signal alias shouldn't \ - point to a signal alias.", - file!(), - line!() - )), - } - } - /// Takes a signal as input and returns the signal if the signal is of the - /// Signal::Data variant, else the function follows follows the uses the + /// Takes a signal_idx as input and returns the corresponding signal if the + /// corresponding signal is of the Signal::Data variant, else the function the /// SignalIdx in the signal_alias field of Signal::Alias variant to index /// into the signal arena in the all_signals field of the vcd, and returns /// the resulting signal if that signal is a Signal::Data variant, else, /// this function returns an Err. - pub fn dealiasing_signal_lookup<'a>(&'a self, signal: &Signal) -> Result<&'a Signal, String> { + pub fn try_signal_idx_to_signal<'a>( + &'a self, + idx: SignalIdx, + ) -> Result<&'a Signal, String> { + // get the signal pointed to be SignalIdx from the arena + let SignalIdx(idx) = idx; + let signal = &self.all_signals[idx]; + // dereference signal if Signal::Alias, or keep idx if Signal::Data let signal_idx = match signal { Signal::Data { self_idx, .. } => *self_idx, From 746c25b1ba70b9770f971da739b4460d67990c89 Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Tue, 25 Oct 2022 21:32:22 -0400 Subject: [PATCH 2/5] change visibility of and rename Signal to SignalEnum --- src/vcd/parse/events.rs | 20 +++++------ src/vcd/parse/scopes.rs | 6 ++-- src/vcd/signal.rs | 32 ++++++++--------- src/vcd/types.rs | 76 ++++++++++++++++++++--------------------- 4 files changed, 67 insertions(+), 67 deletions(-) diff --git a/src/vcd/parse/events.rs b/src/vcd/parse/events.rs index 8475b4f..79418c0 100644 --- a/src/vcd/parse/events.rs +++ b/src/vcd/parse/events.rs @@ -116,7 +116,7 @@ pub(super) fn parse_events<'a>( let signal = vcd.dealiasing_signal_idx_to_signal_lookup_mut(signal_idx)?; match signal { - Signal::Data { + SignalEnum::Data { name, sig_type, ref mut signal_error, @@ -204,7 +204,7 @@ pub(super) fn parse_events<'a>( Ok(()) } } - Signal::Alias { .. } => { + SignalEnum::Alias { .. } => { let (f, l) = (file!(), line!()); let msg = format!( "Error near {f}:{l}, a signal alias should not point to a signal alias.\n\ @@ -229,7 +229,7 @@ pub(super) fn parse_events<'a>( let signal = vcd.dealiasing_signal_idx_to_signal_lookup_mut(signal_idx)?; match signal { - Signal::Data { + SignalEnum::Data { name, sig_type, ref mut signal_error, @@ -296,7 +296,7 @@ pub(super) fn parse_events<'a>( } Ok(()) } - Signal::Alias { .. } => { + SignalEnum::Alias { .. } => { let (f, l) = (file!(), line!()); let msg = format!( "Error near {f}:{l}, a signal alias should not point to a signal alias.\n\ @@ -320,7 +320,7 @@ pub(super) fn parse_events<'a>( let signal = vcd.dealiasing_signal_idx_to_signal_lookup_mut(signal_idx)?; match signal { - Signal::Data { + SignalEnum::Data { name, sig_type, ref mut signal_error, @@ -387,7 +387,7 @@ pub(super) fn parse_events<'a>( } Ok(()) } - Signal::Alias { .. } => { + SignalEnum::Alias { .. } => { let (f, l) = (file!(), line!()); let msg = format!( "Error near {f}:{l}, a signal alias should not point to a signal alias.\n\ @@ -413,7 +413,7 @@ pub(super) fn parse_events<'a>( let signal = vcd.dealiasing_signal_idx_to_signal_lookup_mut(signal_idx)?; match signal { - Signal::Data { + SignalEnum::Data { name, sig_type, ref mut signal_error, @@ -468,7 +468,7 @@ pub(super) fn parse_events<'a>( string_vals.push(val); Ok(()) } - Signal::Alias { .. } => { + SignalEnum::Alias { .. } => { let (f, l) = (file!(), line!()); let msg = format!( "Error near {f}:{l}, a signal alias should not point to a signal alias.\n\ @@ -492,7 +492,7 @@ pub(super) fn parse_events<'a>( let signal = vcd.dealiasing_signal_idx_to_signal_lookup_mut(signal_idx)?; match signal { - Signal::Data { + SignalEnum::Data { ref mut signal_error, string_vals, byte_len_of_string_tmstmp_vals_on_tmln, @@ -513,7 +513,7 @@ pub(super) fn parse_events<'a>( string_vals.push(val); Ok(()) } - Signal::Alias { .. } => { + SignalEnum::Alias { .. } => { let (f, l) = (file!(), line!()); let msg = format!( "Error near {f}:{l}, a signal alias should not point to a signal alias.\n\ diff --git a/src/vcd/parse/scopes.rs b/src/vcd/parse/scopes.rs index cab951d..406a4f0 100644 --- a/src/vcd/parse/scopes.rs +++ b/src/vcd/parse/scopes.rs @@ -95,7 +95,7 @@ pub(super) fn parse_var<'a>( let full_signal_name = full_signal_name.join(" "); let num_bytes = if num_bits.is_some() { - let bytes_required = Signal::bytes_required(num_bits.unwrap(), &full_signal_name)?; + let bytes_required = SignalEnum::bytes_required(num_bits.unwrap(), &full_signal_name)?; Some(bytes_required) } else { None @@ -107,7 +107,7 @@ pub(super) fn parse_var<'a>( let (signal, signal_idx) = match signal_map.get(&signal_alias) { Some(ref_signal_idx) => { let signal_idx = SignalIdx(vcd.all_signals.len()); - let signal = Signal::Alias { + let signal = SignalEnum::Alias { name: full_signal_name, signal_alias: *ref_signal_idx, }; @@ -116,7 +116,7 @@ pub(super) fn parse_var<'a>( None => { let signal_idx = SignalIdx(vcd.all_signals.len()); signal_map.insert(signal_alias.to_string(), signal_idx); - let signal = Signal::Data { + let signal = SignalEnum::Data { name: full_signal_name, sig_type: var_type, signal_error: None, diff --git a/src/vcd/signal.rs b/src/vcd/signal.rs index c32be24..7be10ac 100644 --- a/src/vcd/signal.rs +++ b/src/vcd/signal.rs @@ -30,7 +30,7 @@ pub(super) enum TimelineQueryResults { #[derive(Debug)] -pub enum Signal { +pub(super) enum SignalEnum { Data { name: String, sig_type: SigType, @@ -100,18 +100,18 @@ type TimeStamp = BigUint; type SignalValNum = BigUint; // getter functions -impl Signal { +impl SignalEnum { pub fn name(&self) -> String { match self { - Signal::Data { name, ..} => name, - Signal::Alias { name, .. } => name + SignalEnum::Data { name, ..} => name, + SignalEnum::Alias { name, .. } => name }.clone() } } // helper functions ultimately used by Signal's query functions later on -impl Signal { +impl SignalEnum { /// Computes the bytes required to store a signal's numerical value /// using the num_bits which another function would provide from /// the num_bits field of the Signal::Data variant. @@ -144,7 +144,7 @@ impl Signal { lsb_indxs_of_string_tmstmp_vals_on_tmln, byte_len_of_string_tmstmp_vals_on_tmln, ) = match self { - Signal::Data { + SignalEnum::Data { string_vals, lsb_indxs_of_string_tmstmp_vals_on_tmln, byte_len_of_string_tmstmp_vals_on_tmln, @@ -154,7 +154,7 @@ impl Signal { lsb_indxs_of_string_tmstmp_vals_on_tmln, byte_len_of_string_tmstmp_vals_on_tmln, )), - Signal::Alias { .. } => Err(SignalErrors::PointsToAlias), + SignalEnum::Alias { .. } => Err(SignalErrors::PointsToAlias), }?; // get index @@ -193,7 +193,7 @@ impl Signal { lsb_indxs_of_num_tmstmp_vals_on_tmln, byte_len_of_num_tmstmp_vals_on_tmln, ) = match self { - Signal::Data { + SignalEnum::Data { num_bytes, nums_encoded_as_fixed_width_le_u8, lsb_indxs_of_num_tmstmp_vals_on_tmln, @@ -205,7 +205,7 @@ impl Signal { lsb_indxs_of_num_tmstmp_vals_on_tmln, byte_len_of_num_tmstmp_vals_on_tmln, )), - Signal::Alias { .. } => Err(SignalErrors::PointsToAlias), + SignalEnum::Alias { .. } => Err(SignalErrors::PointsToAlias), }?; // get index @@ -234,12 +234,12 @@ impl Signal { // Function that take in a desired time on the timeline for a // specific signal and return a numerical or string value in a Result, // or an error in a Result. -impl Signal { +impl SignalEnum { pub fn query_string_val_on_tmln( &self, desired_time: &BigUint, tmstmps_encoded_as_u8s: &Vec, - all_signals: &Vec, + all_signals: &Vec, ) -> Result { let signal_idx = match self { Self::Data { self_idx, .. } => { @@ -263,7 +263,7 @@ impl Signal { // else we propagate Err(..). let (string_vals, lsb_indxs_of_string_tmstmp_vals_on_tmln) = match &all_signals[signal_idx] { - Signal::Data { + SignalEnum::Data { ref string_vals, ref lsb_indxs_of_string_tmstmp_vals_on_tmln, .. @@ -273,7 +273,7 @@ impl Signal { lsb_indxs_of_string_tmstmp_vals_on_tmln, )) } - Signal::Alias { .. } => Err(SignalErrors::PointsToAlias), + SignalEnum::Alias { .. } => Err(SignalErrors::PointsToAlias), }?; // this signal should at least have some events, otherwise, trying to index into // an empty vector later on would fail @@ -354,7 +354,7 @@ impl Signal { &self, desired_time: &BigUint, tmstmps_encoded_as_u8s: &Vec, - all_signals: &Vec, + all_signals: &Vec, ) -> Result { let signal_idx = match self { Self::Data { self_idx, .. } => { @@ -379,7 +379,7 @@ impl Signal { // else we propagate Err(..). let (nums_encoded_as_fixed_width_le_u8, lsb_indxs_of_num_tmstmp_vals_on_tmln, num_bytes) = match &all_signals[signal_idx] { - Signal::Data { + SignalEnum::Data { num_bytes, ref nums_encoded_as_fixed_width_le_u8, ref lsb_indxs_of_num_tmstmp_vals_on_tmln, @@ -394,7 +394,7 @@ impl Signal { num_bytes, )) } - Signal::Alias { .. } => Err(SignalErrors::PointsToAlias), + SignalEnum::Alias { .. } => Err(SignalErrors::PointsToAlias), }?; // this signal should at least have some events, otherwise, trying to index into // an empty vector later on would fail diff --git a/src/vcd/types.rs b/src/vcd/types.rs index ad56c3b..78c6748 100644 --- a/src/vcd/types.rs +++ b/src/vcd/types.rs @@ -2,7 +2,7 @@ // This program is distributed under both the GPLV3 license // and the YEHOWSHUA license, both of which can be found at // the root of the folder containing the sources for this program. -use super::Signal; +use super::SignalEnum; use chrono::prelude::*; #[derive(Debug)] @@ -58,7 +58,7 @@ pub struct VCD { // keep track of all timestamp values, a given signal only needs to keep // track of the timestamps at which the given signal value changes. pub(super) tmstmps_encoded_as_u8s: Vec, - pub(super) all_signals: Vec, + pub(super) all_signals: Vec, pub(super) all_scopes: Vec, pub(super) root_scopes: Vec, } @@ -90,23 +90,23 @@ impl VCD { pub(super) fn dealiasing_signal_idx_to_signal_lookup_mut<'a>( &'a mut self, idx: &SignalIdx, - ) -> Result<&'a mut Signal, String> { + ) -> Result<&'a mut SignalEnum, String> { // get the signal pointed to be SignalIdx from the arena let SignalIdx(idx) = idx; let signal = &self.all_signals[*idx]; // dereference signal if Signal::Alias, or keep idx if Signal::Data let signal_idx = match signal { - Signal::Data { self_idx, .. } => *self_idx, - Signal::Alias { name, signal_alias } => *signal_alias, + SignalEnum::Data { self_idx, .. } => *self_idx, + SignalEnum::Alias { name, signal_alias } => *signal_alias, }; // Should now point to Signal::Data variant, or else there's an error let SignalIdx(idx) = signal_idx; let signal = self.all_signals.get_mut(idx).unwrap(); match signal { - Signal::Data { .. } => Ok(signal), - Signal::Alias { .. } => Err(format!( + SignalEnum::Data { .. } => Ok(signal), + SignalEnum::Alias { .. } => Err(format!( "Error near {}:{}. A signal alias shouldn't \ point to a signal alias.", file!(), @@ -114,37 +114,37 @@ impl VCD { )), } } - /// Takes a signal_idx as input and returns the corresponding signal if the - /// corresponding signal is of the Signal::Data variant, else the function the - /// SignalIdx in the signal_alias field of Signal::Alias variant to index - /// into the signal arena in the all_signals field of the vcd, and returns - /// the resulting signal if that signal is a Signal::Data variant, else, - /// this function returns an Err. - pub fn try_signal_idx_to_signal<'a>( - &'a self, - idx: SignalIdx, - ) -> Result<&'a Signal, String> { - // get the signal pointed to be SignalIdx from the arena - let SignalIdx(idx) = idx; - let signal = &self.all_signals[idx]; + // Takes a signal_idx as input and returns the corresponding signal if the + // corresponding signal is of the Signal::Data variant, else the function the + // SignalIdx in the signal_alias field of Signal::Alias variant to index + // into the signal arena in the all_signals field of the vcd, and returns + // the resulting signal if that signal is a Signal::Data variant, else, + // this function returns an Err. + // pub fn try_signal_idx_to_signal<'a>( + // &'a self, + // idx: SignalIdx, + // ) -> Result<&'a Signal, String> { + // // get the signal pointed to be SignalIdx from the arena + // let SignalIdx(idx) = idx; + // let signal = &self.all_signals[idx]; - // dereference signal if Signal::Alias, or keep idx if Signal::Data - let signal_idx = match signal { - Signal::Data { self_idx, .. } => *self_idx, - Signal::Alias { name, signal_alias } => *signal_alias, - }; + // // dereference signal if Signal::Alias, or keep idx if Signal::Data + // let signal_idx = match signal { + // Signal::Data { self_idx, .. } => *self_idx, + // Signal::Alias { name, signal_alias } => *signal_alias, + // }; - // Should now point to Signal::Data variant, or else there's an error - let SignalIdx(idx) = signal_idx; - let signal = self.all_signals.get(idx).unwrap(); - match signal { - Signal::Data { .. } => Ok(signal), - Signal::Alias { .. } => Err(format!( - "Error near {}:{}. A signal alias shouldn't \ - point to a signal alias.", - file!(), - line!() - )), - } - } + // // Should now point to Signal::Data variant, or else there's an error + // let SignalIdx(idx) = signal_idx; + // let signal = self.all_signals.get(idx).unwrap(); + // match signal { + // Signal::Data { .. } => Ok(signal), + // Signal::Alias { .. } => Err(format!( + // "Error near {}:{}. A signal alias shouldn't \ + // point to a signal alias.", + // file!(), + // line!() + // )), + // } + // } } From d343b6f5ff8c8e9c976a7ecfd4ec1e00ed005d82 Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Tue, 25 Oct 2022 22:53:19 -0400 Subject: [PATCH 3/5] I broke something... --- src/vcd/signal.rs | 32 ++++++++++++++++++++++++++++++-- src/vcd/types.rs | 7 +++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/vcd/signal.rs b/src/vcd/signal.rs index 7be10ac..6d8f03b 100644 --- a/src/vcd/signal.rs +++ b/src/vcd/signal.rs @@ -1,3 +1,5 @@ +use crate::VCD; + // 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 @@ -28,6 +30,32 @@ pub(super) enum TimelineQueryResults { String(String), } +pub struct Signal<'a>(pub(super) &'a SignalEnum); + +impl<'a> Signal<'a> { + pub fn name(&self) -> String { + let Signal(signal_enum) = &self; + signal_enum.name() + } + pub fn query_string_val_on_tmln( + &self, + desired_time: &BigUint, + tmstmps_encoded_as_u8s: &Vec, + vcd: &VCD, + ) -> Result { + let Signal(signal_enum) = &self; + signal_enum.query_string_val_on_tmln(desired_time, tmstmps_encoded_as_u8s, &vcd.all_signals) + } + pub fn query_num_val_on_tmln( + &self, + desired_time: &BigUint, + tmstmps_encoded_as_u8s: &Vec, + vcd: &VCD, + ) -> Result { + let Signal(signal_enum) = &self; + signal_enum.query_num_val_on_tmln(desired_time, tmstmps_encoded_as_u8s, &vcd.all_signals) + } +} #[derive(Debug)] pub(super) enum SignalEnum { @@ -134,7 +162,7 @@ impl SignalEnum { /// string_vals field of an instance of the Signal::Data variant /// and gets a string value. /// The function returns a tuple of the timestamp and string value. - pub(super) fn time_and_str_val_at_event_idx( + fn time_and_str_val_at_event_idx( &self, event_idx: usize, tmstmps_encoded_as_u8s: &Vec, @@ -182,7 +210,7 @@ impl SignalEnum { /// numerical value at the time pointed at by event_didx. /// The function returns a tuple of the timestamp and numerical /// value. - pub(super) fn time_and_num_val_at_event_idx( + fn time_and_num_val_at_event_idx( &self, event_idx: usize, tmstmps_encoded_as_u8s: &Vec, diff --git a/src/vcd/types.rs b/src/vcd/types.rs index 78c6748..5dd934d 100644 --- a/src/vcd/types.rs +++ b/src/vcd/types.rs @@ -1,3 +1,5 @@ +use crate::Signal; + // 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 @@ -114,6 +116,11 @@ impl VCD { )), } } + pub fn get_signal<'a>(&'a self, idx: SignalIdx) -> Signal<'a> { + let SignalIdx(idx) = idx; + let signal_enum = &self.all_signals[idx]; + return Signal(signal_enum) + } // Takes a signal_idx as input and returns the corresponding signal if the // corresponding signal is of the Signal::Data variant, else the function the // SignalIdx in the signal_alias field of Signal::Alias variant to index From 9f18b166a5caeeea80992bf42e51a4a6c55b1b82 Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Wed, 26 Oct 2022 01:16:39 -0400 Subject: [PATCH 4/5] sane import and export behaviors --- examples/parse_vcd.rs | 6 ++---- examples/vcd.rs | 2 +- src/lib.rs | 6 +++++- src/vcd.rs | 18 +++++------------- src/vcd/parse.rs | 26 +++++++------------------- src/vcd/parse/combinator_atoms.rs | 2 +- src/vcd/parse/events.rs | 9 ++++++++- src/vcd/parse/metadata.rs | 8 ++++++-- src/vcd/parse/scopes.rs | 12 ++++++++++-- src/vcd/reader.rs | 2 +- src/vcd/signal.rs | 9 ++++----- src/vcd/types.rs | 24 ++++++++++++------------ 12 files changed, 62 insertions(+), 62 deletions(-) diff --git a/examples/parse_vcd.rs b/examples/parse_vcd.rs index 9833f3c..4d7f5da 100644 --- a/examples/parse_vcd.rs +++ b/examples/parse_vcd.rs @@ -5,9 +5,7 @@ use clap::Parser; use std::fs::File; -use fastwave_backend::*; - -use num::{BigUint}; +use fastwave_backend::parse_vcd; #[derive(Parser)] struct Cli { @@ -23,7 +21,7 @@ fn main() -> std::io::Result<()> { let now = Instant::now(); let file = File::open(&args.path)?; - let vcd = parse_vcd(file).unwrap(); + parse_vcd(file).unwrap(); let elapsed = now.elapsed(); println!("Parsed VCD file {} : {:.2?}", &args.path.as_os_str().to_str().unwrap(), elapsed); diff --git a/examples/vcd.rs b/examples/vcd.rs index af552bd..2577410 100644 --- a/examples/vcd.rs +++ b/examples/vcd.rs @@ -4,7 +4,7 @@ // the root of the folder containing the sources for this program. use std::fs::File; -use fastwave_backend::*; +use fastwave_backend::{ScopeIdx, VCD, parse_vcd}; fn indented_print(indent : u8, name : &String) { for _ in 0..indent {print!(" |");} diff --git a/src/lib.rs b/src/lib.rs index f28b750..f73512a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,11 @@ // This program is distributed under both the GPLV3 license // and the YEHOWSHUA license, both of which can be found at // the root of the folder containing the sources for this program. + mod vcd; -pub use vcd::*; +pub use vcd::parse::parse_vcd; +pub use vcd::types::{ScopeIdx, SignalIdx, VCD}; +pub use vcd::types::{Metadata, Timescale, Version}; +pub use vcd::signal::{Signal}; pub use num::BigUint; diff --git a/src/vcd.rs b/src/vcd.rs index 10419ec..fc58b13 100644 --- a/src/vcd.rs +++ b/src/vcd.rs @@ -2,17 +2,9 @@ // This program is distributed under both the GPLV3 license // and the YEHOWSHUA license, both of which can be found at // the root of the folder containing the sources for this program. + mod reader; -use reader::*; - -mod types; -pub use types::*; - -mod parse; -pub use parse::*; - -mod signal; -pub use signal::*; - -mod utilities; -use utilities::*; +pub(crate) mod types; +pub(crate) mod parse; +pub(crate) mod signal; +mod utilities; \ No newline at end of file diff --git a/src/vcd/parse.rs b/src/vcd/parse.rs index fcdd9fe..c89361c 100644 --- a/src/vcd/parse.rs +++ b/src/vcd/parse.rs @@ -2,38 +2,26 @@ // This program is distributed under both the GPLV3 license // and the YEHOWSHUA license, both of which can be found at // the root of the folder containing the sources for this program. -use num::BigUint; -use std::collections::HashMap; use std::fs::File; -use super::*; - mod combinator_atoms; -use combinator_atoms::*; - mod types; -use types::*; - mod metadata; -use metadata::*; - mod scopes; -use scopes::*; - mod events; -use events::*; -pub fn parse_vcd(file: File) -> Result { - let mut word_gen = WordReader::new(file); - let header = parse_metadata(&mut word_gen)?; +pub fn parse_vcd(file: File) -> Result { + let mut word_gen = super::reader::WordReader::new(file); + + let header = metadata::parse_metadata(&mut word_gen)?; // later, we'll need to map parsed ascii symbols to their // respective signal indexes let mut signal_map = std::collections::HashMap::new(); // after we parse metadata, we form the VCD object - let mut vcd = VCD { + let mut vcd = super::types::VCD { metadata: header, tmstmps_encoded_as_u8s: vec![], all_signals: vec![], @@ -41,8 +29,8 @@ pub fn parse_vcd(file: File) -> Result { root_scopes: vec![], }; - parse_scopes(&mut word_gen, &mut vcd, &mut signal_map)?; - parse_events(&mut word_gen, &mut vcd, &mut signal_map)?; + scopes::parse_scopes(&mut word_gen, &mut vcd, &mut signal_map)?; + events::parse_events(&mut word_gen, &mut vcd, &mut signal_map)?; Ok(vcd) } \ No newline at end of file diff --git a/src/vcd/parse/combinator_atoms.rs b/src/vcd/parse/combinator_atoms.rs index 4329831..0473f63 100644 --- a/src/vcd/parse/combinator_atoms.rs +++ b/src/vcd/parse/combinator_atoms.rs @@ -2,7 +2,7 @@ // This program is distributed under both the GPLV3 license // and the YEHOWSHUA license, both of which can be found at // the root of the folder containing the sources for this program. -use super::reader::{next_word, WordReader}; +use super::super::reader::{next_word, WordReader}; use super::types::ParseResult; pub(super) fn digit(chr: u8) -> bool { diff --git a/src/vcd/parse/events.rs b/src/vcd/parse/events.rs index 79418c0..05e24ed 100644 --- a/src/vcd/parse/events.rs +++ b/src/vcd/parse/events.rs @@ -3,7 +3,14 @@ // and the YEHOWSHUA license, both of which can be found at // the root of the folder containing the sources for this program. -use super::*; +use std::collections::HashMap; +use num::BigUint; + +use super::super::utilities::{BinaryParserErrTypes, binary_str_to_vec_u8}; +use super::super::signal::{SignalEnum, LsbIdxOfTmstmpValOnTmln}; +use super::super::reader::{WordReader, Cursor, Line, Word, next_word}; +use super::super::types::{SignalIdx, VCD}; + pub(super) fn parse_events<'a>( word_reader: &mut WordReader, diff --git a/src/vcd/parse/metadata.rs b/src/vcd/parse/metadata.rs index d847f32..6d0fffc 100644 --- a/src/vcd/parse/metadata.rs +++ b/src/vcd/parse/metadata.rs @@ -2,10 +2,14 @@ // This program is distributed under both the GPLV3 license // and the YEHOWSHUA license, both of which can be found at // the root of the folder containing the sources for this program. -use chrono::prelude::*; +use chrono::prelude::{DateTime, Utc, TimeZone}; use itertools::Itertools; -use super::*; +use super::super::reader::{Cursor, WordReader, next_word}; +use super::super::types::{Timescale, Version, Metadata}; + +use super::combinator_atoms::{take_until, take_while, digit, tag}; +use super::types::{ParseResult}; pub(super) fn parse_date( word_and_ctx1: (&str, &Cursor), diff --git a/src/vcd/parse/scopes.rs b/src/vcd/parse/scopes.rs index 406a4f0..94b8965 100644 --- a/src/vcd/parse/scopes.rs +++ b/src/vcd/parse/scopes.rs @@ -5,7 +5,15 @@ /// part of the vcd parser that handles parsing the signal tree and /// building the resulting signal tree -use super::*; + +use std::collections::HashMap; + +use super::super::reader::{WordReader, next_word, curr_word}; +use super::super::types::{VCD, Scope, ScopeIdx, SignalIdx}; +use super::super::signal::{SigType, SignalEnum}; + +use super::combinator_atoms::{tag, ident}; +use super::types::{ParseResult}; pub(super) fn parse_var<'a>( word_reader: &mut WordReader, @@ -322,7 +330,7 @@ pub(super) fn parse_scopes<'a>( signal_map: &mut HashMap, ) -> Result<(), String> { // get the current word - let (word, cursor) = curr_word!(word_reader)?; + let (word, _) = curr_word!(word_reader)?; // we may have orphaned vars that occur before the first scope if word == "$var" { diff --git a/src/vcd/reader.rs b/src/vcd/reader.rs index 4be573f..9fc32ec 100644 --- a/src/vcd/reader.rs +++ b/src/vcd/reader.rs @@ -5,7 +5,7 @@ use std::collections::VecDeque; use std::fs::File; use std::io; -use std::io::prelude::*; +use std::io::BufRead; use std::slice; use std::str; diff --git a/src/vcd/signal.rs b/src/vcd/signal.rs index 6d8f03b..fb15c5a 100644 --- a/src/vcd/signal.rs +++ b/src/vcd/signal.rs @@ -1,10 +1,9 @@ -use crate::VCD; - // 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 // the root of the folder containing the sources for this program. -use super::{ScopeIdx, SignalIdx}; +use super::types::{ScopeIdx, SignalIdx}; +use super::types; use num::{BigUint}; // Index to the least significant byte of a timestamp @@ -41,7 +40,7 @@ impl<'a> Signal<'a> { &self, desired_time: &BigUint, tmstmps_encoded_as_u8s: &Vec, - vcd: &VCD, + vcd: &types::VCD, ) -> Result { let Signal(signal_enum) = &self; signal_enum.query_string_val_on_tmln(desired_time, tmstmps_encoded_as_u8s, &vcd.all_signals) @@ -50,7 +49,7 @@ impl<'a> Signal<'a> { &self, desired_time: &BigUint, tmstmps_encoded_as_u8s: &Vec, - vcd: &VCD, + vcd: &types::VCD, ) -> Result { let Signal(signal_enum) = &self; signal_enum.query_num_val_on_tmln(desired_time, tmstmps_encoded_as_u8s, &vcd.all_signals) diff --git a/src/vcd/types.rs b/src/vcd/types.rs index 5dd934d..60be9bc 100644 --- a/src/vcd/types.rs +++ b/src/vcd/types.rs @@ -1,17 +1,17 @@ -use crate::Signal; +// use crate::Signal; // 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 // the root of the folder containing the sources for this program. -use super::SignalEnum; -use chrono::prelude::*; +use chrono::prelude::{DateTime, Utc}; +use super::signal::{Signal, SignalEnum}; #[derive(Debug)] -pub(super) struct Version(pub String); +pub struct Version(pub String); #[derive(Debug)] -pub(super) enum Timescale { +pub enum Timescale { Fs, Ps, Ns, @@ -22,10 +22,10 @@ pub(super) enum Timescale { } #[derive(Debug)] -pub(super) struct Metadata { - pub(super) date: Option>, - pub(super) version: Option, - pub(super) timescale: (Option, Timescale), +pub struct Metadata { + pub date: Option>, + pub version: Option, + pub timescale: (Option, Timescale), } // We do a lot of arena allocation in this codebase. @@ -48,7 +48,7 @@ pub(super) struct Scope { #[derive(Debug)] pub struct VCD { - pub(super) metadata: Metadata, + pub metadata: Metadata, // Since we only need to store values when there is an actual change // in the timeline, we keep a vector that stores the time at which an // event occurs. Time t is always stored/encoded as the minimum length sequence @@ -100,7 +100,7 @@ impl VCD { // dereference signal if Signal::Alias, or keep idx if Signal::Data let signal_idx = match signal { SignalEnum::Data { self_idx, .. } => *self_idx, - SignalEnum::Alias { name, signal_alias } => *signal_alias, + SignalEnum::Alias {signal_alias, .. } => *signal_alias, }; // Should now point to Signal::Data variant, or else there's an error @@ -119,7 +119,7 @@ impl VCD { pub fn get_signal<'a>(&'a self, idx: SignalIdx) -> Signal<'a> { let SignalIdx(idx) = idx; let signal_enum = &self.all_signals[idx]; - return Signal(signal_enum) + return Signal(signal_enum); } // Takes a signal_idx as input and returns the corresponding signal if the // corresponding signal is of the Signal::Data variant, else the function the From b4cbbf29cc3ec286372d0744415307c456dc2bfd Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Wed, 26 Oct 2022 02:19:59 -0400 Subject: [PATCH 5/5] remove some dead code in comments and add querying values on timeline back to vcd example --- README.md | 4 --- examples/vcd.rs | 76 +++++++++++++++++++++++++++-------------------- src/vcd/signal.rs | 6 ++-- src/vcd/types.rs | 45 ++++------------------------ 4 files changed, 51 insertions(+), 80 deletions(-) diff --git a/README.md b/README.md index 7d44f3e..c96e9a9 100644 --- a/README.md +++ b/README.md @@ -92,11 +92,8 @@ Here's a command to test on a malformed VCD: - [ ] once the access patterns of the GUI frontend are well understood, create specific functions and restrict as many types to private as possible - - [ ] be explicit with imports, remove exports as possible - once FastWave is known to be fairly stable. - [ ] Print out git commit or release number. - [ ] do a read through all the code - look for uneeded code - - [ ] Take a look at GTKWave parser to compare efficiency. - [ ] Move part of the performance section to another markdown file. ## Repairs @@ -108,7 +105,6 @@ Here's a command to test on a malformed VCD: able to successfully parse all sample VCDs. ## Code Consistency - - [ ] split impls in signal.rs into groups - [ ] Change error messages to line and filenames. Go through all calls to unwrap. - [ ] search for any unwraps or any direct vectors indexing - [ ] Handle TODOs diff --git a/examples/vcd.rs b/examples/vcd.rs index 2577410..d89d76a 100644 --- a/examples/vcd.rs +++ b/examples/vcd.rs @@ -4,7 +4,7 @@ // the root of the folder containing the sources for this program. use std::fs::File; -use fastwave_backend::{ScopeIdx, VCD, parse_vcd}; +use fastwave_backend::{ScopeIdx, VCD, parse_vcd, SignalIdx}; fn indented_print(indent : u8, name : &String) { for _ in 0..indent {print!(" |");} @@ -12,29 +12,26 @@ fn indented_print(indent : u8, name : &String) { println!("{name}"); } -fn print_root_scope_tree(root_idx: ScopeIdx, vcd: &VCD, indent : u8) { - if vcd.child_scopes_by_idx(root_idx).is_empty() { - } else { - for child_scope_idx in vcd.child_scopes_by_idx(root_idx) { - indented_print(indent, vcd.scope_name_by_idx(child_scope_idx)); - // for signal_idx in vcd.get_children_signal_idxs(child_scope_idx) { - // let signal = vcd.try_signal_idx_to_signal(signal_idx).unwrap(); - // match signal { - // Signal::Data {..} => {} - // Signal::Alias {..} => {} - // } - // // let to_print = format!("{},{}", signal.name(), ) - // } - // vcd.try_signal_idx_to_signal(idx) - print_root_scope_tree(child_scope_idx, vcd.clone(), indent + 1); +// TODO: refactor into more general visitor pattern that takes a +// function as an argument. +fn visit_all_scopes(vcd: &VCD) { + fn visit_all_scope_children(root_idx: ScopeIdx, vcd: &VCD, indent : u8) { + if vcd.child_scopes_by_idx(root_idx).is_empty() { + } else { + for child_scope_idx in vcd.child_scopes_by_idx(root_idx) { + indented_print(indent, vcd.scope_name_by_idx(child_scope_idx)); + for signal_idx in vcd.get_children_signal_idxs(child_scope_idx) { + let signal = vcd.signal_from_signal_idx(signal_idx); + let SignalIdx(idx) = signal_idx; + indented_print(indent + 1, &format!("{},{}", signal.name(), idx)); + } + visit_all_scope_children(child_scope_idx, vcd.clone(), indent + 1); + } } } -} - -fn ui_all_scopes(vcd: &VCD) { for root_scope_idx in vcd.root_scopes_by_idx() { indented_print(0, vcd.scope_name_by_idx(root_scope_idx)); - print_root_scope_tree(root_scope_idx, vcd, 1u8); + visit_all_scope_children(root_scope_idx, vcd, 1u8); } } @@ -42,6 +39,8 @@ fn main() -> std::io::Result<()> { use std::time::Instant; + // we start by printing out the entire signal tree of + // a parsed VCD let now = Instant::now(); let file_path = "tests/vcd-files/icarus/CPU.vcd"; let file = File::open(file_path)?; @@ -50,25 +49,36 @@ fn main() -> std::io::Result<()> { println!("Parsed VCD file {} : {:.2?}", file_path, elapsed); println!("Printing Scopes"); - ui_all_scopes(&vcd); + visit_all_scopes(&vcd); + println!("Done Printing Scopes"); + println!(); + // we then parse another VCD, print its signal tree and + // query some values on its timeline + let now = Instant::now(); let file_path = "tests/vcd-files/amaranth/up_counter.vcd"; let file = File::open(file_path)?; let vcd = parse_vcd(file).unwrap(); - // let state_signal = vcd.all_si - // for signal_idx in vcd.si - // let name = state_signal.name(); - // let time = BigUint::from(57760000u32); - // let val = state_signal - // .query_string_val_on_tmln( - // &time, - // &vcd.tmstmps_encoded_as_u8s, - // &vcd.all_signals, - // ) - // .unwrap(); - // println!("Signal `{name}` has value `{val}` at time `{time}`"); + let elapsed = now.elapsed(); + println!("Parsed VCD file {} : {:.2?}", file_path, elapsed); + println!("Printing Scopes"); + visit_all_scopes(&vcd); + println!("Done Printing Scopes"); + + let state_signal = vcd.signal_from_signal_idx(SignalIdx(4)); + let name = state_signal.name(); + + 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(); + println!("Signal `{name}` has value `{val}` at time `{time}`"); + + } Ok(()) } diff --git a/src/vcd/signal.rs b/src/vcd/signal.rs index fb15c5a..1688f92 100644 --- a/src/vcd/signal.rs +++ b/src/vcd/signal.rs @@ -39,20 +39,18 @@ impl<'a> Signal<'a> { pub fn query_string_val_on_tmln( &self, desired_time: &BigUint, - tmstmps_encoded_as_u8s: &Vec, vcd: &types::VCD, ) -> Result { let Signal(signal_enum) = &self; - signal_enum.query_string_val_on_tmln(desired_time, tmstmps_encoded_as_u8s, &vcd.all_signals) + signal_enum.query_string_val_on_tmln(desired_time, &vcd.tmstmps_encoded_as_u8s, &vcd.all_signals) } pub fn query_num_val_on_tmln( &self, desired_time: &BigUint, - tmstmps_encoded_as_u8s: &Vec, vcd: &types::VCD, ) -> Result { let Signal(signal_enum) = &self; - signal_enum.query_num_val_on_tmln(desired_time, tmstmps_encoded_as_u8s, &vcd.all_signals) + signal_enum.query_num_val_on_tmln(desired_time, &vcd.tmstmps_encoded_as_u8s, &vcd.all_signals) } } diff --git a/src/vcd/types.rs b/src/vcd/types.rs index 60be9bc..27b682b 100644 --- a/src/vcd/types.rs +++ b/src/vcd/types.rs @@ -33,7 +33,7 @@ pub struct Metadata { pub struct ScopeIdx(pub usize); #[derive(Debug, Copy, Clone, PartialEq)] -pub struct SignalIdx(pub(super) usize); +pub struct SignalIdx(pub usize); #[derive(Debug)] pub(super) struct Scope { @@ -84,6 +84,11 @@ impl VCD { let scope = &self.all_scopes[idx]; &scope.name } + pub fn signal_from_signal_idx<'a>(&'a self, idx: SignalIdx) -> Signal<'a> { + let SignalIdx(idx) = idx; + let signal_enum = &self.all_signals[idx]; + return Signal(signal_enum); + } /// We take in a Signal and attempt to de-alias that signal if it is of /// variant ``Signal::Alias``. If it is of variant ``Signal::Alias`` and points to /// another alias, that's an error. Otherwise, we return the ``Signal::Data`` @@ -116,42 +121,4 @@ impl VCD { )), } } - pub fn get_signal<'a>(&'a self, idx: SignalIdx) -> Signal<'a> { - let SignalIdx(idx) = idx; - let signal_enum = &self.all_signals[idx]; - return Signal(signal_enum); - } - // Takes a signal_idx as input and returns the corresponding signal if the - // corresponding signal is of the Signal::Data variant, else the function the - // SignalIdx in the signal_alias field of Signal::Alias variant to index - // into the signal arena in the all_signals field of the vcd, and returns - // the resulting signal if that signal is a Signal::Data variant, else, - // this function returns an Err. - // pub fn try_signal_idx_to_signal<'a>( - // &'a self, - // idx: SignalIdx, - // ) -> Result<&'a Signal, String> { - // // get the signal pointed to be SignalIdx from the arena - // let SignalIdx(idx) = idx; - // let signal = &self.all_signals[idx]; - - // // dereference signal if Signal::Alias, or keep idx if Signal::Data - // let signal_idx = match signal { - // Signal::Data { self_idx, .. } => *self_idx, - // Signal::Alias { name, signal_alias } => *signal_alias, - // }; - - // // Should now point to Signal::Data variant, or else there's an error - // let SignalIdx(idx) = signal_idx; - // let signal = self.all_signals.get(idx).unwrap(); - // match signal { - // Signal::Data { .. } => Ok(signal), - // Signal::Alias { .. } => Err(format!( - // "Error near {}:{}. A signal alias shouldn't \ - // point to a signal alias.", - // file!(), - // line!() - // )), - // } - // } }