first commit
This commit is contained in:
commit
bf4e793ea3
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
/target
|
||||||
|
Cargo.lock
|
10
Cargo.toml
Normal file
10
Cargo.toml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[package]
|
||||||
|
name = "VCDViewer"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
num = "0.4"
|
||||||
|
clap = { version = "3.1.8", features = ["derive"] }
|
43
README.md
Normal file
43
README.md
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
# The Beginnings of a high-performance, low memory footprint VCD Viewer in Rust for massive multi-GB waveforms
|
||||||
|
|
||||||
|
## Features
|
||||||
|
- very fast
|
||||||
|
- loads 200MB of VCD waveform per second on an 8 core 2017 desktop CPU with NVMe storage
|
||||||
|
- consumes roughly between 10 - 50MB of memory per GB of waveform
|
||||||
|
- elegant/pretty UI
|
||||||
|
- can be easily ported to work in browser via webassembly
|
||||||
|
- allows high-performance custom Rust plugins to manipulate and
|
||||||
|
generate new waveforms live
|
||||||
|
|
||||||
|
## Running
|
||||||
|
|
||||||
|
Make sure you have a test vcd file to get you started. You can grab
|
||||||
|
a large VCD file from
|
||||||
|
[here](https://drive.google.com/file/d/1pfm2qo2l8fGTHHJ8TLrg1vSGaV_TUbp2/view?usp=sharing).
|
||||||
|
|
||||||
|
The first build of the program may take some time.
|
||||||
|
|
||||||
|
``cargo run --release -- path/to/vcd/file``
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
- [x] Test positions with seeking
|
||||||
|
- [x] vcd should be argument
|
||||||
|
- [x] structure to store stream position against timestamp as string
|
||||||
|
- [x] structure to store stream position against timestamp as BigInt
|
||||||
|
|
||||||
|
### April 14
|
||||||
|
- [ ] store timestamps to struct
|
||||||
|
- [ ] Get file loading status
|
||||||
|
- [ ] Get all signal scopes
|
||||||
|
|
||||||
|
### April 15
|
||||||
|
- [ ] Re-factor to support hooks in the initial file ingest
|
||||||
|
- [ ] Modularize
|
||||||
|
|
||||||
|
### April 15
|
||||||
|
- [ ] Build tree per signal.
|
||||||
|
- [ ] Each signal also comes with a value change buffer to
|
||||||
|
avoid frequent disk readouts.
|
||||||
|
|
||||||
|
# VCD Spec Questions
|
||||||
|
- [ ] I'm pretty sure that only one statement per line is allowed.
|
60
src/main.rs
Normal file
60
src/main.rs
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
use std::io::prelude::*;
|
||||||
|
use std::io;
|
||||||
|
use std::fs::File;
|
||||||
|
|
||||||
|
use num::*;
|
||||||
|
use clap::Parser;
|
||||||
|
|
||||||
|
#[derive(Parser)]
|
||||||
|
struct Cli {
|
||||||
|
/// The path to the file to read
|
||||||
|
#[clap(parse(from_os_str))]
|
||||||
|
path: std::path::PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Timestamp{
|
||||||
|
file_offset: u64,
|
||||||
|
timestamp: BigInt
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> std::io::Result<()> {
|
||||||
|
let args = Cli::parse();
|
||||||
|
|
||||||
|
let file = File::open(&args.path)?;
|
||||||
|
let mut reader = io::BufReader::new(file);
|
||||||
|
|
||||||
|
let mut buffer = String::new();
|
||||||
|
let mut timestamp_offsets = Vec::new();
|
||||||
|
let mut timestamps = Vec::new();
|
||||||
|
|
||||||
|
while {
|
||||||
|
let bytes_read = reader.read_line(&mut buffer).unwrap();
|
||||||
|
bytes_read > 0
|
||||||
|
} {
|
||||||
|
if &buffer[0..1] == "#" {
|
||||||
|
let pos = reader.stream_position().unwrap();
|
||||||
|
timestamp_offsets.push(pos);
|
||||||
|
|
||||||
|
let timestamp = {
|
||||||
|
let len = buffer.len();
|
||||||
|
let str_val = &buffer[1..(len - 1)].as_bytes();
|
||||||
|
BigInt::parse_bytes(str_val, 10).unwrap()
|
||||||
|
};
|
||||||
|
timestamps.push(timestamp);
|
||||||
|
}
|
||||||
|
buffer.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
let index = 4;
|
||||||
|
let timestamp_offset = timestamp_offsets.get(index).unwrap();
|
||||||
|
let timestamp = timestamps.get(index).unwrap();
|
||||||
|
dbg!((timestamp_offset, timestamp));
|
||||||
|
|
||||||
|
// seek to where we found the first timestamp and read
|
||||||
|
// out the next line
|
||||||
|
reader.seek(io::SeekFrom::Start(*timestamp_offset));
|
||||||
|
reader.read_line(&mut buffer);
|
||||||
|
dbg!(buffer);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
Reference in a new issue