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
|
||||||
|
|
|
@ -4,7 +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::{ScopeIdx, VCD, parse_vcd};
|
use fastwave_backend::{ScopeIdx, VCD, parse_vcd, SignalIdx};
|
||||||
|
|
||||||
fn indented_print(indent : u8, name : &String) {
|
fn indented_print(indent : u8, name : &String) {
|
||||||
for _ in 0..indent {print!(" |");}
|
for _ in 0..indent {print!(" |");}
|
||||||
|
@ -12,29 +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
|
||||||
if vcd.child_scopes_by_idx(root_idx).is_empty() {
|
// function as an argument.
|
||||||
} else {
|
fn visit_all_scopes(vcd: &VCD) {
|
||||||
for child_scope_idx in vcd.child_scopes_by_idx(root_idx) {
|
fn visit_all_scope_children(root_idx: ScopeIdx, vcd: &VCD, indent : u8) {
|
||||||
indented_print(indent, vcd.scope_name_by_idx(child_scope_idx));
|
if vcd.child_scopes_by_idx(root_idx).is_empty() {
|
||||||
// for signal_idx in vcd.get_children_signal_idxs(child_scope_idx) {
|
} else {
|
||||||
// let signal = vcd.try_signal_idx_to_signal(signal_idx).unwrap();
|
for child_scope_idx in vcd.child_scopes_by_idx(root_idx) {
|
||||||
// match signal {
|
indented_print(indent, vcd.scope_name_by_idx(child_scope_idx));
|
||||||
// Signal::Data {..} => {}
|
for signal_idx in vcd.get_children_signal_idxs(child_scope_idx) {
|
||||||
// Signal::Alias {..} => {}
|
let signal = vcd.signal_from_signal_idx(signal_idx);
|
||||||
// }
|
let SignalIdx(idx) = signal_idx;
|
||||||
// // let to_print = format!("{},{}", signal.name(), )
|
indented_print(indent + 1, &format!("{},{}", signal.name(), idx));
|
||||||
// }
|
}
|
||||||
// vcd.try_signal_idx_to_signal(idx)
|
visit_all_scope_children(child_scope_idx, vcd.clone(), indent + 1);
|
||||||
print_root_scope_tree(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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,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)?;
|
||||||
|
@ -50,25 +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!();
|
||||||
|
|
||||||
|
|
||||||
|
// 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_path = "tests/vcd-files/amaranth/up_counter.vcd";
|
||||||
let file = File::open(file_path)?;
|
let file = File::open(file_path)?;
|
||||||
let vcd = parse_vcd(file).unwrap();
|
let vcd = parse_vcd(file).unwrap();
|
||||||
// let state_signal = vcd.all_si
|
let elapsed = now.elapsed();
|
||||||
// for signal_idx in vcd.si
|
println!("Parsed VCD file {} : {:.2?}", file_path, elapsed);
|
||||||
// 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}`");
|
|
||||||
|
|
||||||
|
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(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,20 +39,18 @@ impl<'a> Signal<'a> {
|
||||||
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>,
|
|
||||||
vcd: &types::VCD,
|
vcd: &types::VCD,
|
||||||
) -> Result<String, SignalErrors> {
|
) -> Result<String, SignalErrors> {
|
||||||
let Signal(signal_enum) = &self;
|
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(
|
pub fn query_num_val_on_tmln(
|
||||||
&self,
|
&self,
|
||||||
desired_time: &BigUint,
|
desired_time: &BigUint,
|
||||||
tmstmps_encoded_as_u8s: &Vec<u8>,
|
|
||||||
vcd: &types::VCD,
|
vcd: &types::VCD,
|
||||||
) -> Result<BigUint, SignalErrors> {
|
) -> Result<BigUint, SignalErrors> {
|
||||||
let Signal(signal_enum) = &self;
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ pub 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 {
|
||||||
|
@ -84,6 +84,11 @@ impl VCD {
|
||||||
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``
|
||||||
|
@ -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!()
|
|
||||||
// )),
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue