diff --git a/src/hierarchy.rs b/src/hierarchy.rs index 01cf1f0..9e827d9 100644 --- a/src/hierarchy.rs +++ b/src/hierarchy.rs @@ -451,10 +451,6 @@ impl Hierarchy { } impl Hierarchy { - pub(crate) fn num_vars(&self) -> usize { - self.vars.len() - } - pub(crate) fn num_unique_signals(&self) -> usize { self.signal_idx_to_var.len() } diff --git a/src/signals.rs b/src/signals.rs index 9e5e7e9..517a737 100644 --- a/src/signals.rs +++ b/src/signals.rs @@ -5,15 +5,99 @@ use crate::hierarchy::{Hierarchy, SignalLength, SignalRef}; use crate::vcd::usize_div_ceil; use std::collections::HashMap; -use std::fmt::Debug; +use std::fmt::{Debug, Display, Formatter}; pub type Time = u64; #[derive(Debug, Clone, Copy)] pub enum SignalValue<'a> { - Binary(&'a [u8]), + Binary(&'a [u8], u32), + FourValue(&'a [u8], u32), String(&'a str), + Float(f64), } + +impl<'a> Display for SignalValue<'a> { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match &self { + SignalValue::Binary(data, bits) => { + write!(f, "{}", two_state_to_bit_string(data, *bits)) + } + SignalValue::FourValue(data, bits) => { + write!(f, "{}", four_state_to_bit_string(data, *bits)) + } + SignalValue::String(value) => write!(f, "{}", value), + SignalValue::Float(value) => write!(f, "{}", value), + } + } +} + +impl<'a> SignalValue<'a> { + fn to_bit_string(&self) -> Option { + match &self { + SignalValue::Binary(data, bits) => Some(two_state_to_bit_string(data, *bits)), + SignalValue::FourValue(data, bits) => Some(four_state_to_bit_string(data, *bits)), + _ => None, + } + } +} + +fn two_state_to_bit_string(data: &[u8], bits: u32) -> String { + let mut out = String::with_capacity(bits as usize); + if bits == 0 { + return out; + } + + // the first byte might not contain a full 8 bits + let byte0_bits = bits - ((bits / 8) * 8); + let byte0_is_special = byte0_bits > 0; + if byte0_is_special { + let byte0 = data[0]; + for ii in (0..byte0_bits).rev() { + let value = (byte0 >> ii) & 1; + let char = ['0', '1'][value as usize]; + out.push(char); + } + } + + for byte in data.iter().skip(if byte0_is_special { 1 } else { 0 }) { + for ii in (0..8).rev() { + let value = (byte >> ii) & 1; + let char = ['0', '1'][value as usize]; + out.push(char); + } + } + out +} + +fn four_state_to_bit_string(data: &[u8], bits: u32) -> String { + let mut out = String::with_capacity(bits as usize); + if bits == 0 { + return out; + } + + // the first byte might not contain a full 4 bits + let byte0_bits = bits - ((bits / 4) * 4); + let byte0_is_special = byte0_bits > 0; + if byte0_is_special { + let byte = data[0]; + for ii in (0..byte0_bits).rev() { + let value = (byte >> (ii * 2)) & 3; + let char = ['0', '1', 'x', 'z'][value as usize]; + out.push(char); + } + } + + for byte in data.iter().skip(if byte0_is_special { 1 } else { 0 }) { + for ii in (0..4).rev() { + let value = (byte >> (ii * 2)) & 3; + let char = ['0', '1', 'x', 'z'][value as usize]; + out.push(char); + } + } + out +} + /// Specifies the encoding of a signal. #[derive(Debug, Clone, Copy)] pub(crate) enum SignalEncoding { @@ -156,26 +240,6 @@ pub(crate) trait SignalSource { fn get_time_table(&self) -> Vec