Refactor signal #6
|
@ -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,
|
- [ ] once the access patterns of the GUI frontend are well understood,
|
||||||
create specific functions and restrict as many types to private
|
create specific functions and restrict as many types to private
|
||||||
as possible
|
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.
|
- [ ] Print out git commit or release number.
|
||||||
- [ ] do a read through all the code - look for uneeded code
|
- [ ] 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.
|
- [ ] Move part of the performance section to another markdown file.
|
||||||
|
|
||||||
## Repairs
|
## Repairs
|
||||||
|
@ -108,7 +105,6 @@ Here's a command to test on a malformed VCD:
|
||||||
able to successfully parse all sample VCDs.
|
able to successfully parse all sample VCDs.
|
||||||
|
|
||||||
## Code Consistency
|
## Code Consistency
|
||||||
- [ ] split impls in signal.rs into groups
|
|
||||||
- [ ] Change error messages to line and filenames. Go through all calls to unwrap.
|
- [ ] Change error messages to line and filenames. Go through all calls to unwrap.
|
||||||
- [ ] search for any unwraps or any direct vectors indexing
|
- [ ] search for any unwraps or any direct vectors indexing
|
||||||
- [ ] Handle TODOs
|
- [ ] Handle TODOs
|
||||||
|
|
|
@ -5,9 +5,7 @@
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
|
||||||
use fastwave_backend::*;
|
use fastwave_backend::parse_vcd;
|
||||||
|
|
||||||
use num::{BigUint};
|
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
struct Cli {
|
struct Cli {
|
||||||
|
@ -23,7 +21,7 @@ fn main() -> std::io::Result<()> {
|
||||||
|
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
let file = File::open(&args.path)?;
|
let file = File::open(&args.path)?;
|
||||||
let vcd = parse_vcd(file).unwrap();
|
parse_vcd(file).unwrap();
|
||||||
let elapsed = now.elapsed();
|
let elapsed = now.elapsed();
|
||||||
|
|
||||||
println!("Parsed VCD file {} : {:.2?}", &args.path.as_os_str().to_str().unwrap(), elapsed);
|
println!("Parsed VCD file {} : {:.2?}", &args.path.as_os_str().to_str().unwrap(), elapsed);
|
||||||
|
|
|
@ -4,9 +4,7 @@
|
||||||
// the root of the folder containing the sources for this program.
|
// the root of the folder containing the sources for this program.
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
|
||||||
use fastwave_backend::*;
|
use fastwave_backend::{ScopeIdx, VCD, parse_vcd, SignalIdx};
|
||||||
|
|
||||||
use num::{BigUint};
|
|
||||||
|
|
||||||
fn indented_print(indent : u8, name : &String) {
|
fn indented_print(indent : u8, name : &String) {
|
||||||
for _ in 0..indent {print!(" |");}
|
for _ in 0..indent {print!(" |");}
|
||||||
|
@ -14,21 +12,26 @@ fn indented_print(indent : u8, name : &String) {
|
||||||
println!("{name}");
|
println!("{name}");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_root_scope_tree(root_idx: ScopeIdx, vcd: &VCD, indent : u8) {
|
// 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() {
|
if vcd.child_scopes_by_idx(root_idx).is_empty() {
|
||||||
} else {
|
} else {
|
||||||
for child_scope_idx in vcd.child_scopes_by_idx(root_idx) {
|
for child_scope_idx in vcd.child_scopes_by_idx(root_idx) {
|
||||||
indented_print(indent, vcd.scope_name_by_idx(child_scope_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) {
|
||||||
print_root_scope_tree(child_scope_idx, vcd.clone(), indent + 1);
|
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() {
|
for root_scope_idx in vcd.root_scopes_by_idx() {
|
||||||
indented_print(0, vcd.scope_name_by_idx(root_scope_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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +39,8 @@ fn main() -> std::io::Result<()> {
|
||||||
|
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
|
// we start by printing out the entire signal tree of
|
||||||
|
// a parsed VCD
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
let file_path = "tests/vcd-files/icarus/CPU.vcd";
|
let file_path = "tests/vcd-files/icarus/CPU.vcd";
|
||||||
let file = File::open(file_path)?;
|
let file = File::open(file_path)?;
|
||||||
|
@ -44,21 +49,36 @@ fn main() -> std::io::Result<()> {
|
||||||
println!("Parsed VCD file {} : {:.2?}", file_path, elapsed);
|
println!("Parsed VCD file {} : {:.2?}", file_path, elapsed);
|
||||||
|
|
||||||
println!("Printing Scopes");
|
println!("Printing Scopes");
|
||||||
ui_all_scopes(&vcd);
|
visit_all_scopes(&vcd);
|
||||||
|
println!("Done Printing Scopes");
|
||||||
|
println!();
|
||||||
|
|
||||||
|
|
||||||
// let state_signal = vcd.
|
// we then parse another VCD, print its signal tree and
|
||||||
// let name = state_signal.name();
|
// query some values on its timeline
|
||||||
// let time = BigUint::from(57760000u32);
|
let now = Instant::now();
|
||||||
// let val = state_signal
|
let file_path = "tests/vcd-files/amaranth/up_counter.vcd";
|
||||||
// .query_string_val_on_tmln(
|
let file = File::open(file_path)?;
|
||||||
// &time,
|
let vcd = parse_vcd(file).unwrap();
|
||||||
// &vcd.tmstmps_encoded_as_u8s,
|
let elapsed = now.elapsed();
|
||||||
// &vcd.all_signals,
|
println!("Parsed VCD file {} : {:.2?}", file_path, elapsed);
|
||||||
// )
|
|
||||||
// .unwrap();
|
|
||||||
// println!("Signal `{name}` has value `{val}` at time `{time}`");
|
|
||||||
|
|
||||||
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,11 @@
|
||||||
// This program is distributed under both the GPLV3 license
|
// This program is distributed under both the GPLV3 license
|
||||||
// and the YEHOWSHUA license, both of which can be found at
|
// and the YEHOWSHUA license, both of which can be found at
|
||||||
// the root of the folder containing the sources for this program.
|
// the root of the folder containing the sources for this program.
|
||||||
|
|
||||||
mod vcd;
|
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;
|
pub use num::BigUint;
|
||||||
|
|
16
src/vcd.rs
16
src/vcd.rs
|
@ -2,17 +2,9 @@
|
||||||
// This program is distributed under both the GPLV3 license
|
// This program is distributed under both the GPLV3 license
|
||||||
// and the YEHOWSHUA license, both of which can be found at
|
// and the YEHOWSHUA license, both of which can be found at
|
||||||
// the root of the folder containing the sources for this program.
|
// the root of the folder containing the sources for this program.
|
||||||
|
|
||||||
mod reader;
|
mod reader;
|
||||||
use reader::*;
|
pub(crate) mod types;
|
||||||
|
pub(crate) mod parse;
|
||||||
mod types;
|
pub(crate) mod signal;
|
||||||
pub use types::*;
|
|
||||||
|
|
||||||
mod parse;
|
|
||||||
pub use parse::*;
|
|
||||||
|
|
||||||
mod signal;
|
|
||||||
pub use signal::*;
|
|
||||||
|
|
||||||
mod utilities;
|
mod utilities;
|
||||||
use utilities::*;
|
|
||||||
|
|
|
@ -2,38 +2,26 @@
|
||||||
// This program is distributed under both the GPLV3 license
|
// This program is distributed under both the GPLV3 license
|
||||||
// and the YEHOWSHUA license, both of which can be found at
|
// and the YEHOWSHUA license, both of which can be found at
|
||||||
// the root of the folder containing the sources for this program.
|
// the root of the folder containing the sources for this program.
|
||||||
use num::BigUint;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
mod combinator_atoms;
|
mod combinator_atoms;
|
||||||
use combinator_atoms::*;
|
|
||||||
|
|
||||||
mod types;
|
mod types;
|
||||||
use types::*;
|
|
||||||
|
|
||||||
mod metadata;
|
mod metadata;
|
||||||
use metadata::*;
|
|
||||||
|
|
||||||
mod scopes;
|
mod scopes;
|
||||||
use scopes::*;
|
|
||||||
|
|
||||||
mod events;
|
mod events;
|
||||||
use events::*;
|
|
||||||
|
|
||||||
pub fn parse_vcd(file: File) -> Result<VCD, String> {
|
|
||||||
let mut word_gen = WordReader::new(file);
|
|
||||||
|
|
||||||
let header = parse_metadata(&mut word_gen)?;
|
pub fn parse_vcd(file: File) -> Result<super::types::VCD, String> {
|
||||||
|
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
|
// later, we'll need to map parsed ascii symbols to their
|
||||||
// respective signal indexes
|
// respective signal indexes
|
||||||
let mut signal_map = std::collections::HashMap::new();
|
let mut signal_map = std::collections::HashMap::new();
|
||||||
|
|
||||||
// after we parse metadata, we form the VCD object
|
// after we parse metadata, we form the VCD object
|
||||||
let mut vcd = VCD {
|
let mut vcd = super::types::VCD {
|
||||||
metadata: header,
|
metadata: header,
|
||||||
tmstmps_encoded_as_u8s: vec![],
|
tmstmps_encoded_as_u8s: vec![],
|
||||||
all_signals: vec![],
|
all_signals: vec![],
|
||||||
|
@ -41,8 +29,8 @@ pub fn parse_vcd(file: File) -> Result<VCD, String> {
|
||||||
root_scopes: vec![],
|
root_scopes: vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
parse_scopes(&mut word_gen, &mut vcd, &mut signal_map)?;
|
scopes::parse_scopes(&mut word_gen, &mut vcd, &mut signal_map)?;
|
||||||
parse_events(&mut word_gen, &mut vcd, &mut signal_map)?;
|
events::parse_events(&mut word_gen, &mut vcd, &mut signal_map)?;
|
||||||
|
|
||||||
Ok(vcd)
|
Ok(vcd)
|
||||||
}
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
// This program is distributed under both the GPLV3 license
|
// This program is distributed under both the GPLV3 license
|
||||||
// and the YEHOWSHUA license, both of which can be found at
|
// and the YEHOWSHUA license, both of which can be found at
|
||||||
// the root of the folder containing the sources for this program.
|
// 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;
|
use super::types::ParseResult;
|
||||||
|
|
||||||
pub(super) fn digit(chr: u8) -> bool {
|
pub(super) fn digit(chr: u8) -> bool {
|
||||||
|
|
|
@ -2,9 +2,15 @@
|
||||||
// This program is distributed under both the GPLV3 license
|
// This program is distributed under both the GPLV3 license
|
||||||
// and the YEHOWSHUA license, both of which can be found at
|
// and the YEHOWSHUA license, both of which can be found at
|
||||||
// the root of the folder containing the sources for this program.
|
// the root of the folder containing the sources for this program.
|
||||||
use num::Zero;
|
|
||||||
|
|
||||||
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>(
|
pub(super) fn parse_events<'a>(
|
||||||
word_reader: &mut WordReader,
|
word_reader: &mut WordReader,
|
||||||
|
@ -13,7 +19,6 @@ pub(super) fn parse_events<'a>(
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
let mut curr_tmstmp_lsb_idx = 0u32;
|
let mut curr_tmstmp_lsb_idx = 0u32;
|
||||||
let mut curr_tmstmp_len_u8 = 0u8;
|
let mut curr_tmstmp_len_u8 = 0u8;
|
||||||
let mut curr_time = BigUint::zero();
|
|
||||||
loop {
|
loop {
|
||||||
let next_word = word_reader.next_word();
|
let next_word = word_reader.next_word();
|
||||||
|
|
||||||
|
@ -42,7 +47,6 @@ pub(super) fn parse_events<'a>(
|
||||||
"Error near {f}:{l}. Failed to parse {value} as BigInt at {cursor:?}"
|
"Error near {f}:{l}. Failed to parse {value} as BigInt at {cursor:?}"
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
curr_time = value.clone();
|
|
||||||
let mut value = value.to_bytes_le();
|
let mut value = value.to_bytes_le();
|
||||||
// TODO : u32 helps with less memory, but should ideally likely be
|
// TODO : u32 helps with less memory, but should ideally likely be
|
||||||
// configurable.
|
// configurable.
|
||||||
|
@ -119,7 +123,7 @@ pub(super) fn parse_events<'a>(
|
||||||
let signal = vcd.dealiasing_signal_idx_to_signal_lookup_mut(signal_idx)?;
|
let signal = vcd.dealiasing_signal_idx_to_signal_lookup_mut(signal_idx)?;
|
||||||
|
|
||||||
match signal {
|
match signal {
|
||||||
Signal::Data {
|
SignalEnum::Data {
|
||||||
name,
|
name,
|
||||||
sig_type,
|
sig_type,
|
||||||
ref mut signal_error,
|
ref mut signal_error,
|
||||||
|
@ -207,7 +211,7 @@ pub(super) fn parse_events<'a>(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Signal::Alias { .. } => {
|
SignalEnum::Alias { .. } => {
|
||||||
let (f, l) = (file!(), line!());
|
let (f, l) = (file!(), line!());
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
"Error near {f}:{l}, a signal alias should not point to a signal alias.\n\
|
"Error near {f}:{l}, a signal alias should not point to a signal alias.\n\
|
||||||
|
@ -232,7 +236,7 @@ pub(super) fn parse_events<'a>(
|
||||||
let signal = vcd.dealiasing_signal_idx_to_signal_lookup_mut(signal_idx)?;
|
let signal = vcd.dealiasing_signal_idx_to_signal_lookup_mut(signal_idx)?;
|
||||||
|
|
||||||
match signal {
|
match signal {
|
||||||
Signal::Data {
|
SignalEnum::Data {
|
||||||
name,
|
name,
|
||||||
sig_type,
|
sig_type,
|
||||||
ref mut signal_error,
|
ref mut signal_error,
|
||||||
|
@ -299,7 +303,7 @@ pub(super) fn parse_events<'a>(
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Signal::Alias { .. } => {
|
SignalEnum::Alias { .. } => {
|
||||||
let (f, l) = (file!(), line!());
|
let (f, l) = (file!(), line!());
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
"Error near {f}:{l}, a signal alias should not point to a signal alias.\n\
|
"Error near {f}:{l}, a signal alias should not point to a signal alias.\n\
|
||||||
|
@ -323,7 +327,7 @@ pub(super) fn parse_events<'a>(
|
||||||
let signal = vcd.dealiasing_signal_idx_to_signal_lookup_mut(signal_idx)?;
|
let signal = vcd.dealiasing_signal_idx_to_signal_lookup_mut(signal_idx)?;
|
||||||
|
|
||||||
match signal {
|
match signal {
|
||||||
Signal::Data {
|
SignalEnum::Data {
|
||||||
name,
|
name,
|
||||||
sig_type,
|
sig_type,
|
||||||
ref mut signal_error,
|
ref mut signal_error,
|
||||||
|
@ -390,7 +394,7 @@ pub(super) fn parse_events<'a>(
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Signal::Alias { .. } => {
|
SignalEnum::Alias { .. } => {
|
||||||
let (f, l) = (file!(), line!());
|
let (f, l) = (file!(), line!());
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
"Error near {f}:{l}, a signal alias should not point to a signal alias.\n\
|
"Error near {f}:{l}, a signal alias should not point to a signal alias.\n\
|
||||||
|
@ -416,13 +420,12 @@ pub(super) fn parse_events<'a>(
|
||||||
let signal = vcd.dealiasing_signal_idx_to_signal_lookup_mut(signal_idx)?;
|
let signal = vcd.dealiasing_signal_idx_to_signal_lookup_mut(signal_idx)?;
|
||||||
|
|
||||||
match signal {
|
match signal {
|
||||||
Signal::Data {
|
SignalEnum::Data {
|
||||||
name,
|
name,
|
||||||
sig_type,
|
sig_type,
|
||||||
ref mut signal_error,
|
ref mut signal_error,
|
||||||
num_bits,
|
num_bits,
|
||||||
string_vals,
|
string_vals,
|
||||||
byte_len_of_num_tmstmp_vals_on_tmln,
|
|
||||||
byte_len_of_string_tmstmp_vals_on_tmln,
|
byte_len_of_string_tmstmp_vals_on_tmln,
|
||||||
lsb_indxs_of_string_tmstmp_vals_on_tmln,
|
lsb_indxs_of_string_tmstmp_vals_on_tmln,
|
||||||
..
|
..
|
||||||
|
@ -472,7 +475,7 @@ pub(super) fn parse_events<'a>(
|
||||||
string_vals.push(val);
|
string_vals.push(val);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Signal::Alias { .. } => {
|
SignalEnum::Alias { .. } => {
|
||||||
let (f, l) = (file!(), line!());
|
let (f, l) = (file!(), line!());
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
"Error near {f}:{l}, a signal alias should not point to a signal alias.\n\
|
"Error near {f}:{l}, a signal alias should not point to a signal alias.\n\
|
||||||
|
@ -496,13 +499,9 @@ pub(super) fn parse_events<'a>(
|
||||||
let signal = vcd.dealiasing_signal_idx_to_signal_lookup_mut(signal_idx)?;
|
let signal = vcd.dealiasing_signal_idx_to_signal_lookup_mut(signal_idx)?;
|
||||||
|
|
||||||
match signal {
|
match signal {
|
||||||
Signal::Data {
|
SignalEnum::Data {
|
||||||
name,
|
|
||||||
sig_type,
|
|
||||||
ref mut signal_error,
|
ref mut signal_error,
|
||||||
num_bits,
|
|
||||||
string_vals,
|
string_vals,
|
||||||
byte_len_of_num_tmstmp_vals_on_tmln,
|
|
||||||
byte_len_of_string_tmstmp_vals_on_tmln,
|
byte_len_of_string_tmstmp_vals_on_tmln,
|
||||||
lsb_indxs_of_string_tmstmp_vals_on_tmln,
|
lsb_indxs_of_string_tmstmp_vals_on_tmln,
|
||||||
..
|
..
|
||||||
|
@ -521,7 +520,7 @@ pub(super) fn parse_events<'a>(
|
||||||
string_vals.push(val);
|
string_vals.push(val);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Signal::Alias { .. } => {
|
SignalEnum::Alias { .. } => {
|
||||||
let (f, l) = (file!(), line!());
|
let (f, l) = (file!(), line!());
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
"Error near {f}:{l}, a signal alias should not point to a signal alias.\n\
|
"Error near {f}:{l}, a signal alias should not point to a signal alias.\n\
|
||||||
|
|
|
@ -2,10 +2,14 @@
|
||||||
// This program is distributed under both the GPLV3 license
|
// This program is distributed under both the GPLV3 license
|
||||||
// and the YEHOWSHUA license, both of which can be found at
|
// and the YEHOWSHUA license, both of which can be found at
|
||||||
// the root of the folder containing the sources for this program.
|
// the root of the folder containing the sources for this program.
|
||||||
use chrono::prelude::*;
|
use chrono::prelude::{DateTime, Utc, TimeZone};
|
||||||
use itertools::Itertools;
|
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(
|
pub(super) fn parse_date(
|
||||||
word_and_ctx1: (&str, &Cursor),
|
word_and_ctx1: (&str, &Cursor),
|
||||||
|
|
|
@ -5,7 +5,15 @@
|
||||||
|
|
||||||
/// part of the vcd parser that handles parsing the signal tree and
|
/// part of the vcd parser that handles parsing the signal tree and
|
||||||
/// building the resulting signal tree
|
/// 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>(
|
pub(super) fn parse_var<'a>(
|
||||||
word_reader: &mut WordReader,
|
word_reader: &mut WordReader,
|
||||||
|
@ -95,7 +103,7 @@ pub(super) fn parse_var<'a>(
|
||||||
let full_signal_name = full_signal_name.join(" ");
|
let full_signal_name = full_signal_name.join(" ");
|
||||||
|
|
||||||
let num_bytes = if num_bits.is_some() {
|
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)
|
Some(bytes_required)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -107,7 +115,7 @@ pub(super) fn parse_var<'a>(
|
||||||
let (signal, signal_idx) = match signal_map.get(&signal_alias) {
|
let (signal, signal_idx) = match signal_map.get(&signal_alias) {
|
||||||
Some(ref_signal_idx) => {
|
Some(ref_signal_idx) => {
|
||||||
let signal_idx = SignalIdx(vcd.all_signals.len());
|
let signal_idx = SignalIdx(vcd.all_signals.len());
|
||||||
let signal = Signal::Alias {
|
let signal = SignalEnum::Alias {
|
||||||
name: full_signal_name,
|
name: full_signal_name,
|
||||||
signal_alias: *ref_signal_idx,
|
signal_alias: *ref_signal_idx,
|
||||||
};
|
};
|
||||||
|
@ -116,7 +124,7 @@ pub(super) fn parse_var<'a>(
|
||||||
None => {
|
None => {
|
||||||
let signal_idx = SignalIdx(vcd.all_signals.len());
|
let signal_idx = SignalIdx(vcd.all_signals.len());
|
||||||
signal_map.insert(signal_alias.to_string(), signal_idx);
|
signal_map.insert(signal_alias.to_string(), signal_idx);
|
||||||
let signal = Signal::Data {
|
let signal = SignalEnum::Data {
|
||||||
name: full_signal_name,
|
name: full_signal_name,
|
||||||
sig_type: var_type,
|
sig_type: var_type,
|
||||||
signal_error: None,
|
signal_error: None,
|
||||||
|
@ -322,7 +330,7 @@ pub(super) fn parse_scopes<'a>(
|
||||||
signal_map: &mut HashMap<String, SignalIdx>,
|
signal_map: &mut HashMap<String, SignalIdx>,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
// get the current word
|
// 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
|
// we may have orphaned vars that occur before the first scope
|
||||||
if word == "$var" {
|
if word == "$var" {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::prelude::*;
|
use std::io::BufRead;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
// This program is distributed under both the GPLV3 license
|
// This program is distributed under both the GPLV3 license
|
||||||
// and the YEHOWSHUA license, both of which can be found at
|
// and the YEHOWSHUA license, both of which can be found at
|
||||||
// the root of the folder containing the sources for this program.
|
// 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};
|
use num::{BigUint};
|
||||||
|
|
||||||
// Index to the least significant byte of a timestamp
|
// Index to the least significant byte of a timestamp
|
||||||
|
@ -28,8 +29,33 @@ pub(super) enum TimelineQueryResults {
|
||||||
String(String),
|
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,
|
||||||
|
vcd: &types::VCD,
|
||||||
|
) -> Result<String, SignalErrors> {
|
||||||
|
let Signal(signal_enum) = &self;
|
||||||
|
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,
|
||||||
|
vcd: &types::VCD,
|
||||||
|
) -> Result<BigUint, SignalErrors> {
|
||||||
|
let Signal(signal_enum) = &self;
|
||||||
|
signal_enum.query_num_val_on_tmln(desired_time, &vcd.tmstmps_encoded_as_u8s, &vcd.all_signals)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Signal {
|
pub(super) enum SignalEnum {
|
||||||
Data {
|
Data {
|
||||||
name: String,
|
name: String,
|
||||||
sig_type: SigType,
|
sig_type: SigType,
|
||||||
|
@ -99,30 +125,18 @@ type TimeStamp = BigUint;
|
||||||
type SignalValNum = BigUint;
|
type SignalValNum = BigUint;
|
||||||
|
|
||||||
// getter functions
|
// getter functions
|
||||||
impl Signal {
|
impl SignalEnum {
|
||||||
pub fn self_idx(&self) -> Result<SignalIdx, String> {
|
|
||||||
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 {
|
pub fn name(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
Signal::Data { name, ..} => name,
|
SignalEnum::Data { name, ..} => name,
|
||||||
Signal::Alias { name, .. } => name
|
SignalEnum::Alias { name, .. } => name
|
||||||
}.clone()
|
}.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// helper functions ultimately used by Signal's query functions later on
|
// 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
|
/// Computes the bytes required to store a signal's numerical value
|
||||||
/// using the num_bits which another function would provide from
|
/// using the num_bits which another function would provide from
|
||||||
/// the num_bits field of the Signal::Data variant.
|
/// the num_bits field of the Signal::Data variant.
|
||||||
|
@ -145,7 +159,7 @@ impl Signal {
|
||||||
/// string_vals field of an instance of the Signal::Data variant
|
/// string_vals field of an instance of the Signal::Data variant
|
||||||
/// and gets a string value.
|
/// and gets a string value.
|
||||||
/// The function returns a tuple of the timestamp and 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,
|
&self,
|
||||||
event_idx: usize,
|
event_idx: usize,
|
||||||
tmstmps_encoded_as_u8s: &Vec<u8>,
|
tmstmps_encoded_as_u8s: &Vec<u8>,
|
||||||
|
@ -155,7 +169,7 @@ impl Signal {
|
||||||
lsb_indxs_of_string_tmstmp_vals_on_tmln,
|
lsb_indxs_of_string_tmstmp_vals_on_tmln,
|
||||||
byte_len_of_string_tmstmp_vals_on_tmln,
|
byte_len_of_string_tmstmp_vals_on_tmln,
|
||||||
) = match self {
|
) = match self {
|
||||||
Signal::Data {
|
SignalEnum::Data {
|
||||||
string_vals,
|
string_vals,
|
||||||
lsb_indxs_of_string_tmstmp_vals_on_tmln,
|
lsb_indxs_of_string_tmstmp_vals_on_tmln,
|
||||||
byte_len_of_string_tmstmp_vals_on_tmln,
|
byte_len_of_string_tmstmp_vals_on_tmln,
|
||||||
|
@ -165,7 +179,7 @@ impl Signal {
|
||||||
lsb_indxs_of_string_tmstmp_vals_on_tmln,
|
lsb_indxs_of_string_tmstmp_vals_on_tmln,
|
||||||
byte_len_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
|
// get index
|
||||||
|
@ -193,7 +207,7 @@ impl Signal {
|
||||||
/// numerical value at the time pointed at by event_didx.
|
/// numerical value at the time pointed at by event_didx.
|
||||||
/// The function returns a tuple of the timestamp and numerical
|
/// The function returns a tuple of the timestamp and numerical
|
||||||
/// value.
|
/// value.
|
||||||
pub(super) fn time_and_num_val_at_event_idx(
|
fn time_and_num_val_at_event_idx(
|
||||||
&self,
|
&self,
|
||||||
event_idx: usize,
|
event_idx: usize,
|
||||||
tmstmps_encoded_as_u8s: &Vec<u8>,
|
tmstmps_encoded_as_u8s: &Vec<u8>,
|
||||||
|
@ -204,7 +218,7 @@ impl Signal {
|
||||||
lsb_indxs_of_num_tmstmp_vals_on_tmln,
|
lsb_indxs_of_num_tmstmp_vals_on_tmln,
|
||||||
byte_len_of_num_tmstmp_vals_on_tmln,
|
byte_len_of_num_tmstmp_vals_on_tmln,
|
||||||
) = match self {
|
) = match self {
|
||||||
Signal::Data {
|
SignalEnum::Data {
|
||||||
num_bytes,
|
num_bytes,
|
||||||
nums_encoded_as_fixed_width_le_u8,
|
nums_encoded_as_fixed_width_le_u8,
|
||||||
lsb_indxs_of_num_tmstmp_vals_on_tmln,
|
lsb_indxs_of_num_tmstmp_vals_on_tmln,
|
||||||
|
@ -216,7 +230,7 @@ impl Signal {
|
||||||
lsb_indxs_of_num_tmstmp_vals_on_tmln,
|
lsb_indxs_of_num_tmstmp_vals_on_tmln,
|
||||||
byte_len_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
|
// get index
|
||||||
|
@ -245,12 +259,12 @@ impl Signal {
|
||||||
// Function that take in a desired time on the timeline for a
|
// Function that take in a desired time on the timeline for a
|
||||||
// specific signal and return a numerical or string value in a Result,
|
// specific signal and return a numerical or string value in a Result,
|
||||||
// or an error in a Result.
|
// or an error in a Result.
|
||||||
impl Signal {
|
impl SignalEnum {
|
||||||
pub fn query_string_val_on_tmln(
|
pub fn query_string_val_on_tmln(
|
||||||
&self,
|
&self,
|
||||||
desired_time: &BigUint,
|
desired_time: &BigUint,
|
||||||
tmstmps_encoded_as_u8s: &Vec<u8>,
|
tmstmps_encoded_as_u8s: &Vec<u8>,
|
||||||
all_signals: &Vec<Signal>,
|
all_signals: &Vec<SignalEnum>,
|
||||||
) -> Result<String, SignalErrors> {
|
) -> Result<String, SignalErrors> {
|
||||||
let signal_idx = match self {
|
let signal_idx = match self {
|
||||||
Self::Data { self_idx, .. } => {
|
Self::Data { self_idx, .. } => {
|
||||||
|
@ -274,7 +288,7 @@ impl Signal {
|
||||||
// else we propagate Err(..).
|
// else we propagate Err(..).
|
||||||
let (string_vals, lsb_indxs_of_string_tmstmp_vals_on_tmln) =
|
let (string_vals, lsb_indxs_of_string_tmstmp_vals_on_tmln) =
|
||||||
match &all_signals[signal_idx] {
|
match &all_signals[signal_idx] {
|
||||||
Signal::Data {
|
SignalEnum::Data {
|
||||||
ref string_vals,
|
ref string_vals,
|
||||||
ref lsb_indxs_of_string_tmstmp_vals_on_tmln,
|
ref lsb_indxs_of_string_tmstmp_vals_on_tmln,
|
||||||
..
|
..
|
||||||
|
@ -284,7 +298,7 @@ impl Signal {
|
||||||
lsb_indxs_of_string_tmstmp_vals_on_tmln,
|
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
|
// this signal should at least have some events, otherwise, trying to index into
|
||||||
// an empty vector later on would fail
|
// an empty vector later on would fail
|
||||||
|
@ -365,7 +379,7 @@ impl Signal {
|
||||||
&self,
|
&self,
|
||||||
desired_time: &BigUint,
|
desired_time: &BigUint,
|
||||||
tmstmps_encoded_as_u8s: &Vec<u8>,
|
tmstmps_encoded_as_u8s: &Vec<u8>,
|
||||||
all_signals: &Vec<Signal>,
|
all_signals: &Vec<SignalEnum>,
|
||||||
) -> Result<BigUint, SignalErrors> {
|
) -> Result<BigUint, SignalErrors> {
|
||||||
let signal_idx = match self {
|
let signal_idx = match self {
|
||||||
Self::Data { self_idx, .. } => {
|
Self::Data { self_idx, .. } => {
|
||||||
|
@ -390,7 +404,7 @@ impl Signal {
|
||||||
// else we propagate Err(..).
|
// else we propagate Err(..).
|
||||||
let (nums_encoded_as_fixed_width_le_u8, lsb_indxs_of_num_tmstmp_vals_on_tmln, num_bytes) =
|
let (nums_encoded_as_fixed_width_le_u8, lsb_indxs_of_num_tmstmp_vals_on_tmln, num_bytes) =
|
||||||
match &all_signals[signal_idx] {
|
match &all_signals[signal_idx] {
|
||||||
Signal::Data {
|
SignalEnum::Data {
|
||||||
num_bytes,
|
num_bytes,
|
||||||
ref nums_encoded_as_fixed_width_le_u8,
|
ref nums_encoded_as_fixed_width_le_u8,
|
||||||
ref lsb_indxs_of_num_tmstmp_vals_on_tmln,
|
ref lsb_indxs_of_num_tmstmp_vals_on_tmln,
|
||||||
|
@ -405,7 +419,7 @@ impl Signal {
|
||||||
num_bytes,
|
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
|
// this signal should at least have some events, otherwise, trying to index into
|
||||||
// an empty vector later on would fail
|
// an empty vector later on would fail
|
||||||
|
|
|
@ -1,15 +1,17 @@
|
||||||
|
// use crate::Signal;
|
||||||
|
|
||||||
// Copyright (C) 2022 Yehowshua Immanuel
|
// Copyright (C) 2022 Yehowshua Immanuel
|
||||||
// This program is distributed under both the GPLV3 license
|
// This program is distributed under both the GPLV3 license
|
||||||
// and the YEHOWSHUA license, both of which can be found at
|
// and the YEHOWSHUA license, both of which can be found at
|
||||||
// the root of the folder containing the sources for this program.
|
// the root of the folder containing the sources for this program.
|
||||||
use super::Signal;
|
use chrono::prelude::{DateTime, Utc};
|
||||||
use chrono::prelude::*;
|
use super::signal::{Signal, SignalEnum};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(super) struct Version(pub String);
|
pub struct Version(pub String);
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(super) enum Timescale {
|
pub enum Timescale {
|
||||||
Fs,
|
Fs,
|
||||||
Ps,
|
Ps,
|
||||||
Ns,
|
Ns,
|
||||||
|
@ -20,10 +22,10 @@ pub(super) enum Timescale {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(super) struct Metadata {
|
pub struct Metadata {
|
||||||
pub(super) date: Option<DateTime<Utc>>,
|
pub date: Option<DateTime<Utc>>,
|
||||||
pub(super) version: Option<Version>,
|
pub version: Option<Version>,
|
||||||
pub(super) timescale: (Option<u32>, Timescale),
|
pub timescale: (Option<u32>, Timescale),
|
||||||
}
|
}
|
||||||
|
|
||||||
// We do a lot of arena allocation in this codebase.
|
// We do a lot of arena allocation in this codebase.
|
||||||
|
@ -31,7 +33,7 @@ pub(super) struct Metadata {
|
||||||
pub struct ScopeIdx(pub usize);
|
pub struct ScopeIdx(pub usize);
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
pub struct SignalIdx(pub(super) usize);
|
pub struct SignalIdx(pub usize);
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(super) struct Scope {
|
pub(super) struct Scope {
|
||||||
|
@ -46,7 +48,7 @@ pub(super) struct Scope {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct VCD {
|
pub struct VCD {
|
||||||
pub(super) metadata: Metadata,
|
pub metadata: Metadata,
|
||||||
// Since we only need to store values when there is an actual change
|
// 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
|
// 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
|
// event occurs. Time t is always stored/encoded as the minimum length sequence
|
||||||
|
@ -58,7 +60,7 @@ pub struct VCD {
|
||||||
// keep track of all timestamp values, a given signal only needs to keep
|
// keep track of all timestamp values, a given signal only needs to keep
|
||||||
// track of the timestamps at which the given signal value changes.
|
// track of the timestamps at which the given signal value changes.
|
||||||
pub(super) tmstmps_encoded_as_u8s: Vec<u8>,
|
pub(super) tmstmps_encoded_as_u8s: Vec<u8>,
|
||||||
pub(super) all_signals: Vec<Signal>,
|
pub(super) all_signals: Vec<SignalEnum>,
|
||||||
pub(super) all_scopes: Vec<Scope>,
|
pub(super) all_scopes: Vec<Scope>,
|
||||||
pub(super) root_scopes: Vec<ScopeIdx>,
|
pub(super) root_scopes: Vec<ScopeIdx>,
|
||||||
}
|
}
|
||||||
|
@ -72,11 +74,21 @@ impl VCD {
|
||||||
let scope = &self.all_scopes[idx];
|
let scope = &self.all_scopes[idx];
|
||||||
scope.child_scopes.clone()
|
scope.child_scopes.clone()
|
||||||
}
|
}
|
||||||
|
pub fn get_children_signal_idxs(&self, scope_idx: ScopeIdx) -> Vec<SignalIdx> {
|
||||||
|
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 {
|
pub fn scope_name_by_idx(&self, scope_idx: ScopeIdx) -> &String {
|
||||||
let ScopeIdx(idx) = scope_idx;
|
let ScopeIdx(idx) = scope_idx;
|
||||||
let scope = &self.all_scopes[idx];
|
let scope = &self.all_scopes[idx];
|
||||||
&scope.name
|
&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
|
/// 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
|
/// 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``
|
/// another alias, that's an error. Otherwise, we return the ``Signal::Data``
|
||||||
|
@ -85,76 +97,23 @@ impl VCD {
|
||||||
pub(super) fn dealiasing_signal_idx_to_signal_lookup_mut<'a>(
|
pub(super) fn dealiasing_signal_idx_to_signal_lookup_mut<'a>(
|
||||||
&'a mut self,
|
&'a mut self,
|
||||||
idx: &SignalIdx,
|
idx: &SignalIdx,
|
||||||
) -> Result<&'a mut Signal, String> {
|
) -> Result<&'a mut SignalEnum, String> {
|
||||||
// get the signal pointed to be SignalIdx from the arena
|
// get the signal pointed to be SignalIdx from the arena
|
||||||
let SignalIdx(idx) = idx;
|
let SignalIdx(idx) = idx;
|
||||||
let signal = &self.all_signals[*idx];
|
let signal = &self.all_signals[*idx];
|
||||||
|
|
||||||
// dereference signal if Signal::Alias, or keep idx if Signal::Data
|
// dereference signal if Signal::Alias, or keep idx if Signal::Data
|
||||||
let signal_idx = match signal {
|
let signal_idx = match signal {
|
||||||
Signal::Data { self_idx, .. } => *self_idx,
|
SignalEnum::Data { self_idx, .. } => *self_idx,
|
||||||
Signal::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
|
// Should now point to Signal::Data variant, or else there's an error
|
||||||
let SignalIdx(idx) = signal_idx;
|
let SignalIdx(idx) = signal_idx;
|
||||||
let signal = self.all_signals.get_mut(idx).unwrap();
|
let signal = self.all_signals.get_mut(idx).unwrap();
|
||||||
match signal {
|
match signal {
|
||||||
Signal::Data { .. } => Ok(signal),
|
SignalEnum::Data { .. } => Ok(signal),
|
||||||
Signal::Alias { .. } => Err(format!(
|
SignalEnum::Alias { .. } => Err(format!(
|
||||||
"Error near {}:{}. A signal alias shouldn't \
|
|
||||||
point to a signal alias.",
|
|
||||||
file!(),
|
|
||||||
line!()
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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
|
|
||||||
/// 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> {
|
|
||||||
// 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 \
|
"Error near {}:{}. A signal alias shouldn't \
|
||||||
point to a signal alias.",
|
point to a signal alias.",
|
||||||
file!(),
|
file!(),
|
||||||
|
|
Loading…
Reference in a new issue