From 18a69872ab89623a95e8c398f851705ce948e524 Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Mon, 25 Jul 2022 21:16:15 -0400 Subject: [PATCH] saving progress so far --- README.md | 1 + src/main.rs | 8 + src/vcd/parse.rs | 325 ++++++++++++++++++++++++++++++++----- src/vcd/parse/metadata.rs | 4 +- src/vcd/parse/scopes.rs | 1 + src/vcd/reader.rs | 25 ++- src/vcd/types.rs | 53 +++++- test-vcd-files/sources.csv | 21 ++- 8 files changed, 379 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index 90d8723..791fb1f 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ You can run all the tests with ``cargo test`` able to successfully parse all sample VCDs. - [ ] Change error messages to line and filenames. Go through all calls to ``format!`` whilst also keep performance in mind. + - [ ] Create compressed fungible numeric enums with good heuristic support. - [ ] Print out git commit or release number. - [ ] Should be able to load waveform whilst viewing it live. - could be quite challenging to implement for various reasons diff --git a/src/main.rs b/src/main.rs index 5c0d88c..8ff2fef 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,9 +16,17 @@ struct Cli { fn main() -> std::io::Result<()> { let args = Cli::parse(); + use std::time::Instant; + let now = Instant::now(); + let file = File::open(&args.path)?; let vcd = parse_vcd(file).unwrap(); + let elapsed = now.elapsed(); + println!("Elapsed: {:.2?}", elapsed); + + vcd.print_longest_signal(); + // println!("printing signal tree"); // vcd.print_scopes(); diff --git a/src/vcd/parse.rs b/src/vcd/parse.rs index 180bb88..d9a1d0b 100644 --- a/src/vcd/parse.rs +++ b/src/vcd/parse.rs @@ -1,5 +1,6 @@ use std::{fs::File}; use std::collections::HashMap; +use chrono::format::format; use num::BigInt; use num::bigint::ToBigInt; @@ -17,8 +18,84 @@ use metadata::*; mod scopes; use scopes::*; +use std::num::{IntErrorKind, ParseIntError}; + use function_name::named; +/// Sometimes, variables can be listed outside of scopes. +/// We call these floating vars. +pub(super) fn parse_orphaned_vars<'a>( + word_reader : &mut WordReader, + vcd : &'a mut VCD, + signal_map : &mut HashMap +) -> Result<(), String> { + // create scope for unscoped signals if such a scope does not + // yet exist + let scope_name = "Orphaned Signals"; + + // set default scope_idx to the count of existing scope as we + // generally set scope.self_idx to the number of existing scopes + // when that particular scope was inserted + let mut scope_idx = Scope_Idx(vcd.all_scopes.len()); + + // Override scope_idx if we find a scope named "Orphaned Signals" + // already exists + let mut scope_already_exists = false; + for scope in &vcd.all_scopes { + if scope.name == scope_name { + scope_idx = scope.self_idx; + scope_already_exists = true; + break + } + } + + if !scope_already_exists { + vcd.all_scopes.push( + Scope { + name: scope_name.to_string(), + parent_idx: None, + self_idx: scope_idx, + child_signals: vec![], + child_scopes: vec![] + } + ); + vcd.scope_roots.push(scope_idx); + } + + // we can go ahead and parse the current var as we've already encountered + // "$var" before now. + parse_var(word_reader, scope_idx, vcd, signal_map)?; + + loop { + let next_word = word_reader.next_word(); + + // we shouldn't reach the end of the file here... + if next_word.is_none() { + let (f, l )= (file!(), line!()); + let msg = format!("Error near {f}:{l}.\ + Reached end of file without terminating parser"); + Err(msg)?; + }; + + let (word, cursor) = next_word.unwrap(); + + match word { + "$var" => { + parse_var(word_reader, scope_idx, vcd, signal_map)?; + } + "$scope" => {break} + _ => { + let (f, l )= (file!(), line!()); + let msg = format!("Error near {f}:{l}.\ + Expected $scope or $var, found {word} at {cursor:?}"); + Err(msg)?; + } + }; + } + + Ok(()) +} + #[named] fn parse_events<'a>( word_reader : &mut WordReader, @@ -41,9 +118,142 @@ fn parse_events<'a>( "$" => {} "#" => { let value = &word[1..]; - let time_cursor = BigInt::parse_bytes(value.as_bytes(), 10).ok_or( - format!("failed to parse {value} as BigInt at {cursor:?}").as_str())?; - vcd.cursor = time_cursor; + // we try to parse the timestamp into the Value unsigned + // variant used to hold the previous timestamp. Doing this + // may fail with PosOverflow, which we would store in parse_ok, + // and later try to remedy with bigger unsigned variants of Value. + let parse_ok = + if let Value::u8(_) = vcd.cursor { + let value = value.parse::(); + match value { + Ok(value) => { + vcd.cursor = Value::u8(value); + Ok(()) + } + Err(e) => Err(e) + } + } + else if let Value::u16(_) = vcd.cursor { + let value = value.parse::(); + match value { + Ok(value) => { + vcd.cursor = Value::u16(value); + Ok(()) + } + Err(e) => Err(e) + } + } + else if let Value::u32(_) = vcd.cursor { + let value = value.parse::(); + match value { + Ok(value) => { + vcd.cursor = Value::u32(value); + Ok(()) + } + Err(e) => Err(e) + } + } + else if let Value::u64(_) = vcd.cursor { + let value = value.parse::(); + match value { + Ok(value) => { + vcd.cursor = Value::u64(value); + Ok(()) + } + Err(e) => Err(e) + } + } + else { + let value = BigInt::parse_bytes(value.as_bytes(), 10).ok_or( + format!("failed to parse {value} as BigInt at {cursor:?}").as_str())?; + vcd.cursor = Value::BigInt(value); + Ok(()) + }; + + + // If there was no parse error, we don't evaluate any more logic + // in this match arm and simply continue to the next iteration of + // the outer loop to evaluate the next word. + if parse_ok.is_ok() { + continue + } + + // Try parsing value as u16 since there was a previous + // PosOverflow error, and record if this parse attempt + // was Ok or Err in parse_ok. + let parse_ok = + { + let e = parse_ok.unwrap_err(); + // There could have been other parse errors... + // Return Err below if there were. + if e.kind() != &IntErrorKind::PosOverflow { + Err(format!("{e:?}"))?; + } + + match value.parse::() { + Ok(value) => { + vcd.cursor = Value::u16(value); + Ok(()) + } + Err(e) => Err(e) + } + }; + + // If there was no parse error, we don't evaluate any more logic + // in this match arm and simply continue to the next iteration of + // the outer loop to evaluate the next word. + if parse_ok.is_ok() { + continue + } + + // Try parsing value as u32 since there was a previous + // PosOverflow error, and record if this parse attempt + // was Ok or Err in parse_ok. + let parse_ok = + { + let e = parse_ok.unwrap_err(); + // There could have been other parse errors... + // Return Err below if there were. + if e.kind() != &IntErrorKind::PosOverflow { + Err(format!("{e:?}"))?; + } + + match value.parse::() { + Ok(value) => { + vcd.cursor = Value::u32(value); + Ok(()) + } + Err(e) => Err(e) + } + }; + + // If there was no parse error, we don't evaluate any more logic + // in this match arm and simply continue to the next iteration of + // the outer loop to evaluate the next word. + if parse_ok.is_ok() { + continue + } + + // Try parsing value as u64 since there was a previous + // PosOverflow error, and record if this parse attempt + // was Ok or Err in parse_ok. + let parse_ok = + { + let e = parse_ok.unwrap_err(); + // There could have been other parse errors... + // Return Err below if there were. + if e.kind() != &IntErrorKind::PosOverflow { + Err(format!("{e:?}"))?; + } + + match value.parse::() { + Ok(value) => { + vcd.cursor = Value::u64(value); + Ok(()) + } + Err(e) => Err(e) + } + }; } "0" => { // lokup signal idx @@ -68,12 +278,13 @@ fn parse_events<'a>( // after handling potential indirection, go ahead and update the timeline // of the signal signal_idx references - let signal = vcd.all_signals.get_mut(signal_idx).unwrap(); + let signal = vcd.all_signals.get_mut(0usize).unwrap(); + // let signal = vcd.all_signals.get_mut(signal_idx).unwrap(); match signal { Signal::Data {name, sig_type, num_bits, self_idx, timeline, scope_parent} => { let value = 0.to_bigint().unwrap(); - let pair = (TimeStamp(vcd.cursor.clone()), Sig_Value::Numeric(value)); + let pair = (vcd.cursor.clone(), Value::u8(0)); timeline.push(pair); Ok(()) } @@ -86,47 +297,47 @@ fn parse_events<'a>( } }?; } - "1" => { - // lokup signal idx - let hash = &word[1..].to_string(); - let Signal_Idx(ref signal_idx) = signal_map.get(hash).ok_or( - format!("failed to lookup signal {hash} at {cursor:?}").as_str())?; + // "1" => { + // // lokup signal idx + // let hash = &word[1..].to_string(); + // let Signal_Idx(ref signal_idx) = signal_map.get(hash).ok_or( + // format!("failed to lookup signal {hash} at {cursor:?}").as_str())?; - // account for fact that signal idx could be an alias, so there - // could be one step of indirection - let signal_idx = - { - let signal = vcd.all_signals.get(*signal_idx).unwrap(); - match signal { - Signal::Data {..} => {signal_idx.clone()} - Signal::Alias {name, signal_alias} => { - let Signal_Idx(ref signal_idx) = signal_alias; - signal_idx.clone() + // // account for fact that signal idx could be an alias, so there + // // could be one step of indirection + // let signal_idx = + // { + // let signal = vcd.all_signals.get(*signal_idx).unwrap(); + // match signal { + // Signal::Data {..} => {signal_idx.clone()} + // Signal::Alias {name, signal_alias} => { + // let Signal_Idx(ref signal_idx) = signal_alias; + // signal_idx.clone() - } - } - }; + // } + // } + // }; - // after handling potential indirection, go ahead and update the timeline - // of the signal signal_idx references - let signal = vcd.all_signals.get_mut(signal_idx).unwrap(); - match signal { - Signal::Data {name, sig_type, num_bits, - self_idx, timeline, scope_parent} => { - let value = 1.to_bigint().unwrap(); - let pair = (TimeStamp(vcd.cursor.clone()), Sig_Value::Numeric(value)); - timeline.push(pair); - Ok(()) - } - Signal::Alias {..} => { - let (f, l )= (file!(), line!()); - let msg = format!( - "Error near {f}:{l}, a signal alias should not point to a signal alias.\n\ - This error occurred while parsing vcd file at {cursor:?}"); - Err(msg) - } - }?; - } + // // after handling potential indirection, go ahead and update the timeline + // // of the signal signal_idx references + // let signal = vcd.all_signals.get_mut(signal_idx).unwrap(); + // match signal { + // Signal::Data {name, sig_type, num_bits, + // self_idx, timeline, scope_parent} => { + // let value = 1.to_bigint().unwrap(); + // let pair = (TimeStamp(vcd.cursor.clone()), Sig_Value::Numeric(value)); + // timeline.push(pair); + // Ok(()) + // } + // Signal::Alias {..} => { + // let (f, l )= (file!(), line!()); + // let msg = format!( + // "Error near {f}:{l}, a signal alias should not point to a signal alias.\n\ + // This error occurred while parsing vcd file at {cursor:?}"); + // Err(msg) + // } + // }?; + // } _ => {} } } @@ -139,17 +350,41 @@ pub fn parse_vcd(file : File) -> Result { let header = 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 VCD object let mut vcd = VCD{ metadata : header, - cursor : 0.to_bigint().unwrap(), + cursor : Value::u8(0), all_signals: vec![], all_scopes : vec![], scope_roots: vec![], }; - parse_scopes(&mut word_gen, None, &mut vcd, &mut signal_map)?; + // The last word parse_metadata saw determines how we proceed. + // There may be some orphan vars we must parse first before + // parsing scoped vars. + let (f, l ) = (file!(), line!()); + let msg = format!("Error near {f}:{l}. Current word empty!"); + let (word, cursor) = word_gen.curr_word().expect(msg.as_str()); + match word { + "$scope" => { + parse_scopes(&mut word_gen, None, &mut vcd, &mut signal_map) + } + "$var" => { + parse_orphaned_vars(&mut word_gen, &mut vcd, &mut signal_map)?; + parse_scopes(&mut word_gen, None, &mut vcd, &mut signal_map) + } + _ => { + let (f, l )= (file!(), line!()); + let msg = format!("Error near {f}:{l}.\ + Expected $scope or $var, found {word} at {cursor:?}"); + Err(msg) + } + + }?; parse_events(&mut word_gen, &mut vcd, &mut signal_map)?; dbg!(&vcd.cursor); diff --git a/src/vcd/parse/metadata.rs b/src/vcd/parse/metadata.rs index 7e0cc91..5d8c956 100644 --- a/src/vcd/parse/metadata.rs +++ b/src/vcd/parse/metadata.rs @@ -315,10 +315,10 @@ pub(super) fn parse_metadata(word_reader : &mut WordReader) -> Result {break} + "var" => {break} // we keep searching for words until we've found one of the following - // keywords, ["version", "timescale", "scope"] + // keywords, ["version", "timescale", "scope", "var"] _ => {} } } diff --git a/src/vcd/parse/scopes.rs b/src/vcd/parse/scopes.rs index d03001c..cbe4ad9 100644 --- a/src/vcd/parse/scopes.rs +++ b/src/vcd/parse/scopes.rs @@ -52,6 +52,7 @@ pub(super) fn parse_var<'a>( // ^ - signal_alias let (word, cursor) = word_reader.next_word().ok_or(&err)?; let signal_alias = word.to_string(); + // dbg!(&signal_alias); // $var parameter 3 a IDLE $end // ^^^^ - full_signal_name(can extend until $end) diff --git a/src/vcd/reader.rs b/src/vcd/reader.rs index a10c4ca..d6437a9 100644 --- a/src/vcd/reader.rs +++ b/src/vcd/reader.rs @@ -5,11 +5,11 @@ use std::str; use std::io::prelude::*; use std::io; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(super) struct Line(pub(super) usize); -#[derive(Debug)] +#[derive(Debug, Clone)] pub(super) struct Word(pub(super) usize); -#[derive(Debug)] +#[derive(Debug, Clone)] pub(super) struct Cursor(pub(super) Line, pub(super) Word); impl Cursor { @@ -26,6 +26,7 @@ pub struct WordReader { buffers : Vec, curr_line : usize, str_slices : VecDeque<(*const u8, usize, Cursor)>, + curr_slice : Option<(*const u8, usize, Cursor)>, } impl WordReader { @@ -36,7 +37,8 @@ impl WordReader { EOF : false, buffers : vec![], curr_line : 0, - str_slices : VecDeque::new() + str_slices : VecDeque::new(), + curr_slice : None } } @@ -83,7 +85,22 @@ impl WordReader { unsafe { let (ptr, len, position) = self.str_slices.pop_front().unwrap(); let slice = slice::from_raw_parts(ptr, len); + self.curr_slice = Some((ptr, len, position.clone())); return Some((str::from_utf8(slice).unwrap(), position)); }; } + + pub(super) fn curr_word(&mut self) -> Option<(&str, Cursor)> { + match &self.curr_slice { + Some(slice) => { + unsafe { + let (ptr, len, position) = slice.clone(); + let slice = slice::from_raw_parts(ptr, len); + Some((str::from_utf8(slice).unwrap(), position)) + } + + } + None => {None} + } + } } \ No newline at end of file diff --git a/src/vcd/types.rs b/src/vcd/types.rs index edaec97..bb9bc2a 100644 --- a/src/vcd/types.rs +++ b/src/vcd/types.rs @@ -1,3 +1,4 @@ +use core::time; use std::collections::{BTreeMap, HashMap}; use chrono::prelude::*; use num::BigInt; @@ -24,11 +25,26 @@ pub(super) struct Signal_Idx(pub(super) usize); pub(super) enum Sig_Type {Integer, Parameter, Real, Reg, Str, Wire, Tri1, Time} #[derive(Debug)] -pub(super) struct TimeStamp(pub(super) BigInt); +pub(super) enum TimeStamp { + u8(u8), + u16(u16), + u32(u32), + u64(u64), + BigInt(BigInt), +} + +#[derive(Debug, Clone)] +pub(super) enum Value { + u8(u8), + u16(u16), + u32(u32), + u64(u64), + BigInt(BigInt), +} #[derive(Debug)] pub(super) enum Sig_Value { - Numeric(BigInt), + Numeric(u64), NonNumeric(String)} #[derive(Debug)] @@ -39,7 +55,7 @@ pub(super) enum Signal{ num_bits : Option, // TODO : may be able to remove self_idx self_idx : Signal_Idx, - timeline : Vec<(TimeStamp, Sig_Value)>, + timeline : Vec<(Value, Value)>, scope_parent : Scope_Idx}, Alias{ name : String, @@ -61,7 +77,7 @@ pub(super) struct Scope { #[derive(Debug)] pub struct VCD { pub(super) metadata : Metadata, - pub (super) cursor : BigInt, + pub (super) cursor : Value, pub(super) all_signals : Vec, pub(super) all_scopes : Vec, pub(super) scope_roots : Vec} @@ -107,4 +123,33 @@ impl VCD { self.print_scope_tree(*scope_root, 0); } } + + pub fn print_longest_signal(&self) { + let mut idx = 0usize; + let mut max_len = 0usize; + let mut signal_name = String::new(); + + for signal in &self.all_signals { + match signal { + Signal::Alias {..} => {} + Signal::Data { + name, + sig_type, + num_bits, + self_idx, + timeline, + scope_parent } => { + if timeline.len() > max_len { + max_len = timeline.len(); + let Signal_Idx(idx_usize) = self_idx; + idx = *idx_usize; + signal_name = name.clone(); + } + + } + } + } + + dbg!((idx, max_len, signal_name)); + } } \ No newline at end of file diff --git a/test-vcd-files/sources.csv b/test-vcd-files/sources.csv index b9b58e9..0f6a722 100644 --- a/test-vcd-files/sources.csv +++ b/test-vcd-files/sources.csv @@ -1,4 +1,17 @@ -Icarus,Verilator,GHDL,VCS,QuestaSim,ModelSim,Quartus,SystemC,Treadle,Aldec,Riviera-PRO,MyHDL,ncsim,xilinx_isim,vivado,GTKWave-Analyzer,Amaranth -https://github.com/dpretet/vcd/blob/master/test1.vcd,https://github.com/wavedrom/vcd-samples/blob/trunk/swerv1.vcd,https://raw.githubusercontent.com/AdoobII/idea_21s/main/vhdl/idea.vcd,https://raw.githubusercontent.com/ameyjain/8-bit-Microprocessor/master/8-bit%20microprocessor/processor.vcd,https://github.com/mr-gaurav/Sequence-Counter/blob/main/test.vcd,https://github.com/Mohammad-Heydariii/Digital-Systems-Lab-Course/blob/main/Lab_project4/modelsim_files/clkdiv2n_tb.vcd,https://github.com/PedroTLemos/ProjetoInfraHard/blob/master/mipsHardware.vcd,https://github.com/jroslindo/Mips-Systemc/blob/main/REGISTRADORES_32_bits/wave_registradores.vcd,https://github.com/chipsalliance/treadle/blob/master/src/test/resources/GCD.vcd,https://github.com/SVeilleux9/FPGA-GPIO-Extender/blob/main/Firmware/aldec/SPI_Write/SPI_Write.vcd,https://github.com/prathampathak/Tic-Tac-Tao/blob/main/dump.vcd,https://github.com/aibtw/myHdl_Projects/blob/main/SimpleMemory/Simple_Memory.vcd,https://github.com/amiteee78/RTL_design/blob/master/ffdiv_32bit/ffdiv_32bit_prop_binom/run_cad/ffdiv_32bit_tb.vcd,https://github.com/mukul54/qrs-peak-fpga/blob/master/utkarsh/utkarsh.sim/sim_1/behav/xsim/test.vcd,https://github.com/saharmalmir/Eth2Ser/blob/master/UART2ETH.runs/impl_1/iladata.vcd,https://github.com/Asfagus/Network-Switch/blob/main/perm_current.vcd,Locally Simulated File -https://github.com/ombhilare999/riscv-core/blob/master/src/rv32_soc_TB.vcd,https://github.com/bigBrain1901/nPOWER-ISA-5-STAGE-PIPELINED-CPU/blob/master/post_compile_files/vlt_dump.vcd,https://github.com/gaoqqt2n/CPU/blob/master/SuperPipelineCPU/vcdfile/pcpu.vcd,https://raw.githubusercontent.com/Akashay-Singla/RISC-V/main/Pipeline/datapath_log.vcd,https://github.com/SparshAgarwal/Computer-Architecture/blob/master/hw3/hw3_1/dump.vcd,https://github.com/sh619/Songyu_Huang-Chisel/blob/main/MU0_final_version/simulation/qsim/CPU_Design.msim.vcd,,https://github.com/amrhas/PDRNoC/blob/VCRouter/noctweak/Debug/waveform.vcd.vcd,,,,https://github.com/Abhishek010397/Programming-RISC-V/blob/master/top.vcd,,https://github.com/DanieleParravicini/regex_coprocessor/blob/master/scripts/sim/test2x2_regex22_string1.vcd,https://github.com/BradMcDanel/multiplication-free-dnn/blob/master/verilog/iladata.vcd,, -https://github.com/b06902044/computer_architecture/blob/main/CPU.vcd,,https://github.com/charlycop/VLSI-1/blob/master/EXEC/ALU/alu.vcd,https://raw.githubusercontent.com/sathyapriyanka/APB_UVC_UVM/main/Apb_slave_uvm_new.vcd,,,,,,,,https://github.com/DarthSkipper/myHDL_Sigmoid/blob/master/out/testbench/sigmoid_tb.vcd,,https://github.com/pabloec1729/Hashes-generator/blob/master/RTL/velocidad/test.vcd,,, +Icarus,https://github.com/dpretet/vcd/blob/master/test1.vcd,https://github.com/ombhilare999/riscv-core/blob/master/src/rv32_soc_TB.vcd,https://github.com/b06902044/computer_architecture/blob/main/CPU.vcd +Verilator,https://github.com/wavedrom/vcd-samples/blob/trunk/swerv1.vcd,https://github.com/bigBrain1901/nPOWER-ISA-5-STAGE-PIPELINED-CPU/blob/master/post_compile_files/vlt_dump.vcd, +GHDL,https://raw.githubusercontent.com/AdoobII/idea_21s/main/vhdl/idea.vcd,https://github.com/gaoqqt2n/CPU/blob/master/SuperPipelineCPU/vcdfile/pcpu.vcd,https://github.com/charlycop/VLSI-1/blob/master/EXEC/ALU/alu.vcd +VCS,https://raw.githubusercontent.com/ameyjain/8-bit-Microprocessor/master/8-bit%20microprocessor/processor.vcd,https://raw.githubusercontent.com/Akashay-Singla/RISC-V/main/Pipeline/datapath_log.vcd,https://raw.githubusercontent.com/sathyapriyanka/APB_UVC_UVM/main/Apb_slave_uvm_new.vcd +QuestaSim,https://github.com/mr-gaurav/Sequence-Counter/blob/main/test.vcd,https://github.com/SparshAgarwal/Computer-Architecture/blob/master/hw3/hw3_1/dump.vcd, +ModelSim,https://github.com/Mohammad-Heydariii/Digital-Systems-Lab-Course/blob/main/Lab_project4/modelsim_files/clkdiv2n_tb.vcd,https://github.com/sh619/Songyu_Huang-Chisel/blob/main/MU0_final_version/simulation/qsim/CPU_Design.msim.vcd, +Quartus,https://github.com/PedroTLemos/ProjetoInfraHard/blob/master/mipsHardware.vcd,, +SystemC,https://github.com/jroslindo/Mips-Systemc/blob/main/REGISTRADORES_32_bits/wave_registradores.vcd,https://github.com/amrhas/PDRNoC/blob/VCRouter/noctweak/Debug/waveform.vcd.vcd, +Treadle,https://github.com/chipsalliance/treadle/blob/master/src/test/resources/GCD.vcd,, +Aldec,https://github.com/SVeilleux9/FPGA-GPIO-Extender/blob/main/Firmware/aldec/SPI_Write/SPI_Write.vcd,, +Riviera-PRO,https://github.com/prathampathak/Tic-Tac-Tao/blob/main/dump.vcd,, +MyHDL,https://github.com/aibtw/myHdl_Projects/blob/main/SimpleMemory/Simple_Memory.vcd,https://github.com/Abhishek010397/Programming-RISC-V/blob/master/top.vcd,https://github.com/DarthSkipper/myHDL_Sigmoid/blob/master/out/testbench/sigmoid_tb.vcd +ncsim,https://github.com/amiteee78/RTL_design/blob/master/ffdiv_32bit/ffdiv_32bit_prop_binom/run_cad/ffdiv_32bit_tb.vcd,, +xilinx_isim,https://github.com/mukul54/qrs-peak-fpga/blob/master/utkarsh/utkarsh.sim/sim_1/behav/xsim/test.vcd,https://github.com/DanieleParravicini/regex_coprocessor/blob/master/scripts/sim/test2x2_regex22_string1.vcd,https://github.com/pabloec1729/Hashes-generator/blob/master/RTL/velocidad/test.vcd +vivado,https://github.com/saharmalmir/Eth2Ser/blob/master/UART2ETH.runs/impl_1/iladata.vcd,https://github.com/BradMcDanel/multiplication-free-dnn/blob/master/verilog/iladata.vcd, +GTKWave-Analyzer,https://github.com/Asfagus/Network-Switch/blob/main/perm_current.vcd,, +Amaranth,Locally Simulated File,, \ No newline at end of file