From 1489f3ffa2b54293c9aff82bef80bf788b22359f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kevin=20L=C3=A4ufer?= Date: Tue, 5 Mar 2024 15:08:39 -0500 Subject: [PATCH] ghw: old test works again --- src/ghw/common.rs | 145 ++++++++++++++++++--- src/ghw/hierarchy.rs | 304 ++++++++++++++++++++++++++----------------- src/ghw/mod.rs | 5 +- src/ghw/signals.rs | 209 +++++++++++++---------------- 4 files changed, 400 insertions(+), 263 deletions(-) diff --git a/src/ghw/common.rs b/src/ghw/common.rs index 67ce4bb..b66818d 100644 --- a/src/ghw/common.rs +++ b/src/ghw/common.rs @@ -188,40 +188,151 @@ impl HeaderData { } } +/// Information needed to read a signal value. +#[derive(Debug, Clone, Copy)] +pub struct GhwSignalInfo { + tpe_and_vec: NonZeroU32, + signal_ref: SignalRef, +} + +impl GhwSignalInfo { + pub fn new(tpe: SignalType, signal_ref: SignalRef, vector: Option) -> Self { + let raw_tpe = ((tpe as u8) as u32) + 1; + debug_assert_eq!(raw_tpe & 0x7, raw_tpe); + let tpe_and_vec = if let Some(vector) = vector { + let raw_vector_id = (vector as u32) + 1; + debug_assert_eq!((raw_vector_id << 3) >> 3, raw_vector_id); + NonZeroU32::new((raw_vector_id << 3) | raw_tpe).unwrap() + } else { + NonZeroU32::new(raw_tpe).unwrap() + }; + Self { + tpe_and_vec, + signal_ref, + } + } + + pub fn signal_ref(&self) -> SignalRef { + self.signal_ref + } + + pub fn vec_id(&self) -> Option { + let vec_id = self.tpe_and_vec.get() >> 3; + if vec_id == 0 { + None + } else { + Some(GhwVecId::new(vec_id as usize)) + } + } + + pub fn tpe(&self) -> SignalType { + let value = self.tpe_and_vec.get(); + let raw_tpe = (value & 0x7) as u8; + let tpe = SignalType::try_from_primitive(raw_tpe - 1).unwrap(); + tpe + } +} + /// Contains information needed in order to decode value changes. #[derive(Debug, Default)] pub struct GhwDecodeInfo { - pub signals: Vec, + /// Type and signal reference info. Indexed by `GhwSignalId` + signals: Vec, + /// Vector info. Indexed by `GhwVecId`. + vectors: Vec, +} + +impl GhwDecodeInfo { + pub fn new(signals: Vec, vectors: Vec) -> Self { + Self { signals, vectors } + } + pub fn is_empty(&self) -> bool { + self.signals.is_empty() + } + pub fn get_info(&self, signal_id: GhwSignalId) -> &GhwSignalInfo { + &self.signals[signal_id.index()] + } + pub fn vectors(&self) -> &[GhwVecInfo] { + &self.vectors + } + pub fn signal_len(&self) -> usize { + self.signals.len() + } +} + +/// Pointer to a `GhwVecInfo` +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct GhwVecId(NonZeroU32); + +impl GhwVecId { + pub fn new(pos_id: usize) -> Self { + Self(NonZeroU32::new(pos_id as u32).unwrap()) + } + + pub fn index(&self) -> usize { + (self.0.get() - 1) as usize + } +} + +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct GhwSignalId(NonZeroU32); + +impl GhwSignalId { + #[inline] + pub fn index(&self) -> usize { + (self.0.get() - 1) as usize + } + pub fn new(pos_id: u32) -> Self { + Self(NonZeroU32::new(pos_id).unwrap()) + } } -/// Holds information from the header needed in order to read the corresponding data in the signal section. -#[derive(Debug, Clone)] -pub struct GhwSignal { - /// Signal ID in the wavemem Encoder. - pub signal_ref: SignalRef, - pub tpe: SignalType, - // currently used for debugging - pub alias_entry: Option, +#[derive(Debug, Clone, Copy)] +pub struct GhwVecInfo { + max: GhwSignalId, + min: GhwSignalId, + two_state: bool, +} + +impl GhwVecInfo { + pub fn new(min: GhwSignalId, max: GhwSignalId, two_state: bool) -> Self { + Self { + min, + max, + two_state, + } + } + pub fn bits(&self) -> u32 { + (self.max.index() - self.min.index() + 1) as u32 + } + pub fn is_two_state(&self) -> bool { + self.two_state + } + pub fn min(&self) -> GhwSignalId { + self.min + } + pub fn max(&self) -> GhwSignalId { + self.max + } } /// Specifies the signal type info that is needed in order to read it. -#[derive(Debug, PartialEq, Copy, Clone)] +#[repr(u8)] +#[derive(Debug, PartialEq, Copy, Clone, TryFromPrimitive)] pub enum SignalType { /// Nine value signal encoded as a single byte. NineState, - /// A single bit in a 9 value bit vector. bit N / M bits. - NineStateBit(u32, u32), + /// A single bit in a 9 value bit vector. + NineStateVec, /// Two value signal encoded as a single byte. TwoState, /// A single bit in a 2 value bit vector. bit N / M bits. - TwoStateBit(u32, u32), + TwoStateVec, /// Binary signal encoded as a single byte with N valid bits. - U8(u32), + U8, /// Binary signal encoded as a variable number of bytes with N valid bits. - #[allow(dead_code)] - Leb128Signed(u32), + Leb128Signed, /// F64 (real) - #[allow(dead_code)] F64, } diff --git a/src/ghw/hierarchy.rs b/src/ghw/hierarchy.rs index 3bbcee8..936bbbe 100644 --- a/src/ghw/hierarchy.rs +++ b/src/ghw/hierarchy.rs @@ -113,12 +113,11 @@ pub(crate) fn try_read_directory( pub(crate) fn read_hierarchy( header: &HeaderData, input: &mut impl BufRead, -) -> Result<(GhwDecodeInfo, usize, Hierarchy)> { +) -> Result<(GhwDecodeInfo, Hierarchy)> { let mut tables = GhwTables::default(); let mut strings = Vec::new(); let mut decode = GhwDecodeInfo::default(); let mut hb = HierarchyBuilder::new(FileFormat::Ghw); - let mut signal_ref_count = 0; // GHW seems to always uses fs hb.set_timescale(Timescale::new(1, TimescaleUnit::FemtoSeconds)); @@ -181,15 +180,14 @@ pub(crate) fn read_hierarchy( } } GHW_HIERARCHY_SECTION => { - let (dec, ref_count) = read_hierarchy_section(header, &mut tables, input, &mut hb)?; + let dec = read_hierarchy_section(header, &mut tables, input, &mut hb)?; debug_assert!( - decode.signals.is_empty(), + decode.is_empty(), "unexpected second hierarchy section:\n{:?}\n{:?}", decode, dec ); decode = dec; - signal_ref_count = ref_count; } GHW_END_OF_HEADER_SECTION => { break; // done @@ -202,7 +200,7 @@ pub(crate) fn read_hierarchy( } } let hierarchy = hb.finish(); - Ok((decode, signal_ref_count, hierarchy)) + Ok((decode, hierarchy)) } /// adds all enums to the hierarchy and @@ -708,7 +706,7 @@ fn read_hierarchy_section( tables: &mut GhwTables, input: &mut impl BufRead, h: &mut HierarchyBuilder, -) -> Result<(GhwDecodeInfo, usize)> { +) -> Result { let mut hdr = [0u8; 16]; input.read_exact(&mut hdr)?; check_header_zeros("hierarchy", &hdr)?; @@ -717,14 +715,13 @@ fn read_hierarchy_section( let _expected_num_scopes = header.read_u32(&mut &hdr[4..8])?; // declared signals, may be composite let expected_num_declared_vars = header.read_u32(&mut &hdr[8..12])?; - let max_signal_id = header.read_u32(&mut &hdr[12..16])? as usize; + let max_signal_id = header.read_u32(&mut &hdr[12..16])?; + println!("Max signal id: {max_signal_id}"); + println!("expected_num_declared_vars {expected_num_declared_vars}"); let mut num_declared_vars = 0; - let mut signals: Vec> = Vec::with_capacity(max_signal_id + 1); - signals.resize(max_signal_id + 1, None); - let mut signal_ref_count = 0; let mut index_string_cache = IndexCache::new(); - let mut aliases = AliasTable::default(); + let mut signal_info = GhwSignals::new(max_signal_id); loop { let kind = GhwHierarchyKind::try_from_primitive(read_u8(input)?)?; @@ -757,11 +754,9 @@ fn read_hierarchy_section( tables, input, kind, - &mut signals, - &mut signal_ref_count, + &mut signal_info, &mut index_string_cache, h, - &mut aliases, )?; num_declared_vars += 1; if num_declared_vars > expected_num_declared_vars { @@ -776,11 +771,12 @@ fn read_hierarchy_section( } } - let decode = GhwDecodeInfo { - signals: signals.into_iter().flatten().collect::>(), - }; + println!("Wellen Signal Refs: {}", signal_info.signal_ref_count); + let decode_info = signal_info.into_decode_info(); + println!("GHW Signals: {}", decode_info.signal_len()); + println!("Vectors: {}", decode_info.vectors().len()); - Ok((decode, signal_ref_count)) + Ok(decode_info) } fn dummy_read_signal_value( @@ -869,11 +865,9 @@ fn read_hierarchy_var( tables: &mut GhwTables, input: &mut impl BufRead, kind: GhwHierarchyKind, - signals: &mut [Option], - signal_ref_count: &mut usize, + signals: &mut GhwSignals, index_string_cache: &mut IndexCache, h: &mut HierarchyBuilder, - aliases: &mut AliasTable, ) -> Result<()> { let name_id = read_string_id(input)?; let name = tables.get_str(name_id); @@ -883,31 +877,13 @@ fn read_hierarchy_var( input, kind, signals, - signal_ref_count, index_string_cache, h, - aliases, name, tpe, ) } -/// Creates a new signal ref unless one is already available (because of aliasing!) -fn get_signal_ref( - signals: &[Option], - signal_ref_count: &mut usize, - index: SignalId, -) -> SignalRef { - match &signals[index.0.get() as usize] { - None => { - let signal_ref = SignalRef::from_index(*signal_ref_count).unwrap(); - *signal_ref_count += 1; - signal_ref - } - Some(signal) => signal.signal_ref, - } -} - type IndexCache = HashMap; fn get_index_string( @@ -925,53 +901,162 @@ fn get_index_string( } } +/// Collects information for every signal id in the GHW file. +/// We store the type information needed to decode the signal as well as +/// information that is needed in order to map the bit-wise signal encoding +/// in a GHW to the bit-vector signal encoding used in our `wellen` wavemem. +#[derive(Debug)] +struct GhwSignals { + signals: Vec>, + signal_ref_count: usize, + vectors: Vec, + aliases: Vec, +} + +/// Used to define aliased signals in the `wellen` wavemem. #[derive(Debug, Clone, Copy)] struct AliasInfo { - min: u32, max: u32, - name: HierarchyStringId, + min: u32, } +impl GhwSignals { + fn new(max_signal_id: u32) -> Self { + let signals = vec![None; max_signal_id as usize]; + let signal_ref_count = 0; + let vectors = vec![]; + let aliases = vec![]; + Self { + signals, + signal_ref_count, + vectors, + aliases, + } + } -// tracking aliasing of BitVec and Bits -#[derive(Debug, Default)] -struct AliasTable { - info: Vec, -} + fn into_decode_info(self) -> GhwDecodeInfo { + let mut signals: Vec<_> = self.signals.into_iter().flatten().collect(); + signals.shrink_to_fit(); + GhwDecodeInfo::new(signals, self.vectors) + } -impl AliasTable { - fn check(&mut self, h: &HierarchyBuilder, prev: Option<&GhwSignal>, min: SignalId, max: SignalId, name: HierarchyStringId) -> NonZeroU32 { - let (min, max) = (min.0.get, max.0.get()) - if let Some(prev_signal) = prev { - let id = prev_signal.alias_entry.unwrap(); - debug_assert!(prev_signal.alias_entry.is_some(), "Expected an alias entry!"); - let entry = self.info[(id.get() - 1) as usize].clone(); + fn max_signal_id(&self) -> usize { + self.signals.len() + } - if entry.min == min && entry.max == max { - id + /// used for f64, i32, i64 and u8 + fn register_scalar(&mut self, signal_id: GhwSignalId, tpe: SignalType) -> SignalRef { + if let Some(prev) = &self.signals[signal_id.index()] { + debug_assert_eq!(prev.tpe(), tpe, "{signal_id:?}"); + prev.signal_ref() + } else { + // create new id + let id = self.new_signal_ref(); + // we do not need to store any extra aliasing info + self.signals[signal_id.index()] = Some(GhwSignalInfo::new(tpe, id, None)); + id + } + } + + fn new_signal_ref(&mut self) -> SignalRef { + let id = SignalRef::from_index(self.signal_ref_count).unwrap(); + self.signal_ref_count += 1; + id + } + + fn register_bit_vec( + &mut self, + min_id: GhwSignalId, + max_id: GhwSignalId, + is_binary: bool, + ) -> SignalRef { + let (min, max) = (min_id.index(), max_id.index()); + debug_assert!(max >= min); + + // check to see if there is already a vector that this signal aliases with + let maybe_vector = self.find_vec(min, max).map(|i| &self.vectors[i.index()]); + if let Some(vector) = maybe_vector { + let (prev_min, prev_max) = (vector.min().index(), vector.max().index()); + if max == prev_max && min == prev_min { + // perfect alias + // just return the signal ref + self.signals[min].unwrap().signal_ref() + } else if prev_min as usize <= min && prev_max as usize >= max { + todo!("sub signal alias!") + } else if prev_min as usize >= min && prev_max as usize <= max { + todo!("super signal alias!") } else { - panic!("Incompatible aliasing between {} ({:?}..{:?}) and {} ({:?}..{:?})",h.get_str(entry.name), entry.min, entry.max, h.get_str(name), min, max) + todo!("overlapped aliased vectors") } } else { - // allocate new entry - let id = NonZeroU32::new(self.info.len() as u32 + 1).unwrap(); - self.info.push(AliasInfo { - min, max, name - }); - id + // no existing vector to alias with + if min == max { + // single bit with no aliased vector behaves essentially like a scalar + if is_binary { + self.register_scalar(min_id, SignalType::TwoState) + } else { + self.register_scalar(min_id, SignalType::NineState) + } + } else { + // for a vector we want to make sure that there are no bits that alias this vector + for ii in min..=max { + // this situation is very unlikely since assigning bit ids first would make it harder for GHDL + // to assign contiguous vec ids + assert!( + self.signals[ii].is_none(), + "TODO: deal with bit that aliases with vector" + ); + } + + // create a new vec entry + let vec_id = self.vectors.len(); + self.vectors + .push(GhwVecInfo::new(min_id, max_id, is_binary)); + let tpe = if is_binary { + SignalType::TwoStateVec + } else { + SignalType::NineStateVec + }; + let id = self.new_signal_ref(); + + // update all bits + for ii in min..=max { + self.signals[ii] = Some(GhwSignalInfo::new(tpe, id, Some(vec_id))); + } + id + } } } + + /// Searches for vector info in the specified range. + #[inline] + fn find_vec(&self, min: usize, max: usize) -> Option { + let mut res = None; + for ii in min..=max { + if let Some(info) = &self.signals[ii] { + let vec_id = info.vec_id(); + debug_assert!( + res.is_none() || vec_id.is_none() || res == vec_id, + "Signal spans several sub-vectors" + ); + res = vec_id; + // early returns in release mode + if !cfg!(debug_assertions) && res.is_some() { + return res; + } + } + } + res + } } fn add_var( tables: &GhwTables, input: &mut impl BufRead, kind: GhwHierarchyKind, - signals: &mut [Option], - signal_ref_count: &mut usize, + signals: &mut GhwSignals, index_string_cache: &mut IndexCache, h: &mut HierarchyBuilder, - aliases: &mut AliasTable, name: HierarchyStringId, type_id: TypeId, ) -> Result<()> { @@ -980,9 +1065,9 @@ fn add_var( match vhdl_tpe { VhdlType::Enum(_, literals, enum_id) => { let enum_type = tables.enums[*enum_id as usize]; - let index = read_signal_id(input, signals)?; - let signal_ref = get_signal_ref(signals, signal_ref_count, index); + let index = read_signal_id(input, signals.max_signal_id())?; let bits = get_enum_bits(&literals); + let signal_ref = signals.register_scalar(index, SignalType::U8); h.add_var( name, VarType::Enum, @@ -993,13 +1078,11 @@ fn add_var( Some(enum_type), Some(tpe_name), ); - // meta date for writing the signal later - let tpe = SignalType::U8(8); // TODO: try to find the actual number of bits used - signals[index.0.get() as usize] = Some(GhwSignal { signal_ref, tpe, alias_entry: None }) } VhdlType::NineValueBit(_) | VhdlType::Bit(_) => { - let index = read_signal_id(input, signals)?; - let signal_ref = get_signal_ref(signals, signal_ref_count, index); + let index = read_signal_id(input, signals.max_signal_id())?; + let is_binary = matches!(vhdl_tpe, VhdlType::Bit(_)); + let signal_ref = signals.register_bit_vec(index, index, is_binary); let var_type = match h.get_str(tpe_name).to_ascii_lowercase().as_str() { "std_ulogic" => VarType::StdULogic, "std_logic" => VarType::StdLogic, @@ -1016,20 +1099,13 @@ fn add_var( None, Some(tpe_name), ); - // meta date for writing the signal later - let tpe = match vhdl_tpe { - VhdlType::Bit(_) => SignalType::TwoState, - _ => SignalType::NineState, - }; - let alias_entry = Some(aliases.check(h, signals[index.0.get() as usize].as_ref(), index, index, name)); - signals[index.0.get() as usize] = Some(GhwSignal { signal_ref, tpe, alias_entry}) } VhdlType::I32(_, maybe_range) => { // TODO: we could use the range to deduce indices and tighter widths let _range = IntRange::from_i32_option(*maybe_range); let bits = 32; - let index = read_signal_id(input, signals)?; - let signal_ref = get_signal_ref(signals, signal_ref_count, index); + let index = read_signal_id(input, signals.max_signal_id())?; + let signal_ref = signals.register_scalar(index, SignalType::Leb128Signed); let var_type = VarType::Integer; h.add_var( name, @@ -1041,16 +1117,13 @@ fn add_var( None, Some(tpe_name), ); - // meta date for writing the signal later - let tpe = SignalType::Leb128Signed(bits); - signals[index.0.get() as usize] = Some(GhwSignal { signal_ref, tpe, alias_entry: None }) } VhdlType::F64(_, maybe_range) => { // TODO: we could use the range to deduce indices and tighter widths let _range = FloatRange::from_f64_option(*maybe_range); let bits = 64; - let index = read_signal_id(input, signals)?; - let signal_ref = get_signal_ref(signals, signal_ref_count, index); + let index = read_signal_id(input, signals.max_signal_id())?; + let signal_ref = signals.register_scalar(index, SignalType::F64); let var_type = VarType::Real; h.add_var( name, @@ -1062,12 +1135,6 @@ fn add_var( None, Some(tpe_name), ); - // meta date for writing the signal later - signals[index.0.get() as usize] = Some(GhwSignal { - signal_ref, - tpe: SignalType::F64, - alias_entry: None, - }) } VhdlType::NineValueVec(_, range) | VhdlType::BitVec(_, range) => { let num_bits = range.len().abs() as u32; @@ -1075,14 +1142,29 @@ fn add_var( // TODO: how should we correctly deal with an empty vector? return Ok(()); } + let mut signal_ids = Vec::with_capacity(num_bits as usize); for _ in 0..num_bits { - signal_ids.push(read_signal_id(input, signals)?); + signal_ids.push(read_signal_id(input, signals.max_signal_id())?); } - for (prev, cur) in signal_ids.iter().take(signal_ids.len() -1).zip(signal_ids.iter().skip(1)) { - debug_assert_eq!(prev.0 .get()+ 1, cur.0.get(), "We expected signal ids increasing by exactly 1, not {prev:?} -> {cur:?}"); + + // check assumption that all IDs are continuous + for (prev, cur) in signal_ids + .iter() + .take(signal_ids.len() - 1) + .zip(signal_ids.iter().skip(1)) + { + debug_assert_eq!( + prev.index() + 1, + cur.index(), + "We expected signal ids increasing by exactly 1, not {prev:?} -> {cur:?}" + ); } - let signal_ref = get_signal_ref(signals, signal_ref_count, signal_ids[0]); + + let is_binary = matches!(vhdl_tpe, VhdlType::BitVec(_, _)); + let min = signal_ids.first().unwrap().clone(); + let max = signal_ids.last().unwrap().clone(); + let signal_ref = signals.register_bit_vec(min, max, is_binary); let var_type = match h.get_str(tpe_name).to_ascii_lowercase().as_str() { "std_ulogic_vector" => VarType::StdULogicVector, "std_logic_vector" => VarType::StdLogicVector, @@ -1099,19 +1181,6 @@ fn add_var( None, Some(tpe_name), ); - // meta date for writing the signal later - let is_bitvec = matches!(vhdl_tpe, VhdlType::BitVec(_, _)); - let min = signal_ids.first().unwrap().clone(); - let max = signal_ids.last().unwrap().clone(); - for (bit, index) in signal_ids.iter().rev().enumerate() { - let tpe = if is_bitvec { - SignalType::TwoStateBit(bit as u32, num_bits) - } else { - SignalType::NineStateBit(bit as u32, num_bits) - }; - let alias_entry = Some(aliases.check(h, signals[index.0.get() as usize].as_ref(), min, max, name)); - signals[index.0.get() as usize] = Some(GhwSignal { signal_ref, tpe, alias_entry }) - } } VhdlType::Record(_, fields) => { h.add_scope(name, None, ScopeType::VhdlRecord, None, None, false); @@ -1121,10 +1190,8 @@ fn add_var( input, kind, signals, - signal_ref_count, index_string_cache, h, - aliases, tables.get_str(*field_name), *field_type, )?; @@ -1142,10 +1209,8 @@ fn add_var( input, kind, signals, - signal_ref_count, index_string_cache, h, - aliases, name, *element_tpe, )?; @@ -1157,15 +1222,15 @@ fn add_var( Ok(()) } -fn read_signal_id(input: &mut impl BufRead, signals: &mut [Option]) -> Result { +fn read_signal_id(input: &mut impl BufRead, max_signal_id: usize) -> Result { let index = leb128::read::unsigned(input)? as usize; - if index >= signals.len() { + if index > max_signal_id { Err(GhwParseError::FailedToParseSection( "hierarchy", - format!("SignalId too large {index} > {}", signals.len()), + format!("SignalId too large {index} > {}", max_signal_id), )) } else { - let id = SignalId(NonZeroU32::new(index as u32).unwrap()); + let id = GhwSignalId::new(index as u32); Ok(id) } } @@ -1197,9 +1262,6 @@ impl TypeId { } } -#[derive(Debug, Copy, Clone, PartialEq)] -struct SignalId(NonZeroU32); - #[derive(Debug)] enum Range { Int(IntRange), diff --git a/src/ghw/mod.rs b/src/ghw/mod.rs index d31c1d1..19ba1f9 100644 --- a/src/ghw/mod.rs +++ b/src/ghw/mod.rs @@ -37,8 +37,7 @@ fn read_internal(input: &mut (impl BufRead + Seek)) -> std::result::Result Result> { // TODO: multi-threading let mut encoder = Encoder::new(hierarchy); - let mut vecs = VecBuffer::from_decode_info(info, signal_ref_count); + let mut vecs = VecBuffer::from_vec_info(info.vectors()); // loop over signal sections loop { @@ -63,8 +62,8 @@ fn read_snapshot_section( let start_time = header.read_i64(&mut &h[4..12])? as u64; enc.time_change(start_time); - for sig in info.signals.iter() { - read_signal_value(sig, vecs, enc, input)?; + for sig_index in 0..(info.signal_len() as u32) { + read_signal_value(info, GhwSignalId::new(sig_index + 1), vecs, enc, input)?; } finish_time_step(vecs, enc); @@ -125,8 +124,8 @@ fn read_cycle_signals( "Expected a first delta > 0".to_string(), )); } - let sig = &info.signals[pos_signal_index - 1]; - read_signal_value(sig, vecs, enc, input)?; + let sig_id = GhwSignalId::new(pos_signal_index as u32); + read_signal_value(info, sig_id, vecs, enc, input)?; } Ok(()) } @@ -134,99 +133,74 @@ fn read_cycle_signals( /// This dispatches any remaining vector changes. fn finish_time_step(vecs: &mut VecBuffer, enc: &mut Encoder) { vecs.process_changed_signals(|signal_ref, data, states| { - enc.raw_value_change(signal_ref, data, states); + todo!("finish timestep with vec_id!"); + // enc.raw_value_change(signal_ref, data, states); }) } fn read_signal_value( - signal: &GhwSignal, + info: &GhwDecodeInfo, + signal_id: GhwSignalId, vecs: &mut VecBuffer, enc: &mut Encoder, input: &mut impl BufRead, ) -> Result<()> { - match signal.tpe { + let signal_info = info.get_info(signal_id); + let (tpe, signal_ref) = (signal_info.tpe(), signal_info.signal_ref()); + match tpe { SignalType::NineState => { let ghdl_value = read_u8(input)?; let value = [STD_LOGIC_LUT[ghdl_value as usize]]; - enc.raw_value_change(signal.signal_ref, &value, States::Nine); + enc.raw_value_change(signal_ref, &value, States::Nine); } SignalType::TwoState => { let value = [read_u8(input)?]; debug_assert!(value[0] <= 1); - enc.raw_value_change(signal.signal_ref, &value, States::Two); + enc.raw_value_change(signal_ref, &value, States::Two); } - SignalType::NineStateBit(bit, _) => { + SignalType::NineStateVec | SignalType::TwoStateVec => { let ghdl_value = read_u8(input)?; - let value = STD_LOGIC_LUT[ghdl_value as usize]; - - // check to see if we already had a change to this same bit in the current time step - if vecs.is_second_change(signal.signal_ref, bit, value) { - // immediately dispatch the change to properly reflect the delta cycle - let data = vecs.get_full_value_and_clear_changes(signal.signal_ref); - enc.raw_value_change(signal.signal_ref, data, States::Nine); - } - - // update value - vecs.update_value(signal.signal_ref, bit, value); + let (value, states) = if tpe == SignalType::NineStateVec { + (STD_LOGIC_LUT[ghdl_value as usize], States::Nine) + } else { + debug_assert!(ghdl_value <= 1); + (ghdl_value, States::Two) + }; - // check to see if we need to report a change - if vecs.full_signal_has_changed(signal.signal_ref) { - let data = vecs.get_full_value_and_clear_changes(signal.signal_ref); - enc.raw_value_change(signal.signal_ref, data, States::Nine); - } - } - SignalType::TwoStateBit(bit, _) => { - let value = read_u8(input)?; - debug_assert!(value <= 1); + let vec_id = signal_info.vec_id().unwrap(); + let vec_info = &info.vectors()[vec_id.index()]; + let bit = (signal_id.index() - vec_info.min().index()) as u32; // check to see if we already had a change to this same bit in the current time step - if vecs.is_second_change(signal.signal_ref, bit, value) { + if vecs.is_second_change(vec_id, bit, value) { // immediately dispatch the change to properly reflect the delta cycle - let data = vecs.get_full_value_and_clear_changes(signal.signal_ref); - enc.raw_value_change(signal.signal_ref, data, States::Two); + let data = vecs.get_full_value_and_clear_changes(vec_id); + enc.raw_value_change(signal_ref, data, states); } // update value - vecs.update_value(signal.signal_ref, bit, value); + vecs.update_value(vec_id, bit, value); // check to see if we need to report a change - if vecs.full_signal_has_changed(signal.signal_ref) { - let data = vecs.get_full_value_and_clear_changes(signal.signal_ref); - enc.raw_value_change(signal.signal_ref, data, States::Two); + if vecs.full_signal_has_changed(vec_id) { + let data = vecs.get_full_value_and_clear_changes(vec_id); + enc.raw_value_change(signal_ref, data, states); } } - SignalType::U8(bits) => { + SignalType::U8 => { let value = [read_u8(input)?]; - if bits < 8 { - debug_assert!(value[0] < (1u8 << bits)); - } - enc.raw_value_change(signal.signal_ref, &value, States::Two); + enc.raw_value_change(signal_ref, &value, States::Two); } - SignalType::Leb128Signed(bits) => { + SignalType::Leb128Signed => { let signed_value = leb128::read::signed(input)?; let value = signed_value as u64; - if bits < u64::BITS { - if signed_value >= 0 { - debug_assert!( - value < (1u64 << bits), - "{value} does not fit into 32 {bits}" - ); - } else { - let non_sign_mask = (1u64 << (bits - 1)) - 1; - let sign_bits = value & !non_sign_mask; - debug_assert_eq!(sign_bits, !non_sign_mask); - } - } - let num_bytes = bits.div_ceil(8) as usize; - let bytes = &value.to_be_bytes()[(8 - num_bytes)..]; - debug_assert_eq!(bytes.len(), num_bytes); - enc.raw_value_change(signal.signal_ref, bytes, States::Two); + let bytes = &value.to_be_bytes(); + enc.raw_value_change(signal_ref, bytes, States::Two); } - SignalType::F64 => { // we need to figure out the endianes here let value = read_f64_le(input)?; - enc.real_change(signal.signal_ref, value); + enc.real_change(signal_ref, value); } } Ok(()) @@ -235,10 +209,10 @@ fn read_signal_value( /// Keeps track of individual bits and combines them into a full bit vector. #[derive(Debug)] struct VecBuffer { - info: Vec>, + info: Vec, data: Vec, bit_change: Vec, - change_list: Vec, + change_list: Vec, signal_change: Vec, } @@ -268,39 +242,32 @@ impl VecBufferInfo { } impl VecBuffer { - fn from_decode_info(decode_info: &GhwDecodeInfo, signal_ref_count: usize) -> Self { - let mut info = Vec::with_capacity(signal_ref_count); - info.resize(signal_ref_count, None); + fn from_vec_info(vectors: &[GhwVecInfo]) -> Self { + let mut info = Vec::with_capacity(vectors.len()); let mut data_start = 0; let mut bit_change_start = 0; - for signal in decode_info.signals.iter() { - if info[signal.signal_ref.index()].is_none() { - match signal.tpe { - SignalType::NineStateBit(0, bits) | SignalType::TwoStateBit(0, bits) => { - let states = if matches!(signal.tpe, SignalType::TwoStateBit(_, _)) { - States::Two - } else { - States::Nine - }; - info[signal.signal_ref.index()] = Some(VecBufferInfo { - data_start: data_start as u32, - bit_change_start: bit_change_start as u32, - bits, - states, - }); - data_start += (bits as usize).div_ceil(states.bits_in_a_byte()); - bit_change_start += (bits as usize).div_ceil(8); - } - _ => {} // do nothing - } - } + for vector in vectors.iter() { + let bits = vector.bits(); + let states = if vector.is_two_state() { + States::Two + } else { + States::Nine + }; + info.push(VecBufferInfo { + data_start: data_start as u32, + bit_change_start: bit_change_start as u32, + bits, + states, + }); + data_start += (bits as usize).div_ceil(states.bits_in_a_byte()); + bit_change_start += (bits as usize).div_ceil(8); } - let data = vec![0; data_start as usize]; - let bit_change = vec![0; bit_change_start as usize]; + let data = vec![0; data_start]; + let bit_change = vec![0; bit_change_start]; let change_list = vec![]; - let signal_change = vec![0; signal_ref_count.div_ceil(8)]; + let signal_change = vec![0; info.len().div_ceil(8)]; Self { info, @@ -311,43 +278,41 @@ impl VecBuffer { } } - fn process_changed_signals(&mut self, mut callback: impl FnMut(SignalRef, &[u8], States)) { + fn process_changed_signals(&mut self, mut callback: impl FnMut(GhwVecId, &[u8], States)) { let change_list = std::mem::take(&mut self.change_list); - for signal_ref in change_list.into_iter() { - if self.has_signal_changed(signal_ref) { - let states = (&self.info[signal_ref.index()].as_ref()).unwrap().states; - let data = self.get_full_value_and_clear_changes(signal_ref); - (callback)(signal_ref, data, states); + for vec_id in change_list.into_iter() { + if self.has_signal_changed(vec_id) { + let states = self.info[vec_id.index()].states; + let data = self.get_full_value_and_clear_changes(vec_id); + (callback)(vec_id, data, states); } } } #[inline] - fn is_second_change(&self, signal_ref: SignalRef, bit: u32, value: u8) -> bool { - let info = (&self.info[signal_ref.index()].as_ref()).unwrap_or_else(|| { - panic!("failed to find signal {signal_ref:?} which has a change! Why is there no read info?") - }); + fn is_second_change(&self, vector_id: GhwVecId, bit: u32, value: u8) -> bool { + let info = &self.info[vector_id.index()]; self.has_bit_changed(info, bit) && self.get_value(info, bit) != value } #[inline] - fn update_value(&mut self, signal_ref: SignalRef, bit: u32, value: u8) { - let info = (&self.info[signal_ref.index()].as_ref()).unwrap(); + fn update_value(&mut self, vector_id: GhwVecId, bit: u32, value: u8) { + let info = &self.info[vector_id.index()]; let is_a_real_change = self.get_value(info, bit) != value; if is_a_real_change { Self::mark_bit_changed(&mut self.bit_change, info, bit); Self::set_value(&mut self.data, info, bit, value); // add signal to change list if it has not already been added - if !self.has_signal_changed(signal_ref) { - self.mark_signal_changed(signal_ref); + if !self.has_signal_changed(vector_id) { + self.mark_signal_changed(vector_id); } } } /// Used in order to dispatch full signal changes as soon as possible #[inline] - fn full_signal_has_changed(&self, signal_ref: SignalRef) -> bool { - let info = (&self.info[signal_ref.index()].as_ref()).unwrap(); + fn full_signal_has_changed(&self, vector_id: GhwVecId) -> bool { + let info = &self.info[vector_id.index()]; // check changes let changes = &self.bit_change[info.change_range()]; @@ -370,8 +335,8 @@ impl VecBuffer { } #[inline] - fn get_full_value_and_clear_changes(&mut self, signal_ref: SignalRef) -> &[u8] { - let info = (&self.info[signal_ref.index()].as_ref()).unwrap(); + fn get_full_value_and_clear_changes(&mut self, vector_id: GhwVecId) -> &[u8] { + let info = &self.info[vector_id.index()]; // clear bit changes let changes = &mut self.bit_change[info.change_range()]; @@ -380,8 +345,8 @@ impl VecBuffer { } // clear signal change - let byte = signal_ref.index() / 8; - let bit = signal_ref.index() % 8; + let byte = vector_id.index() / 8; + let bit = vector_id.index() % 8; self.signal_change[byte] = self.signal_change[byte] & !(1u8 << bit); // note, we keep the signal on the change list @@ -407,18 +372,18 @@ impl VecBuffer { } #[inline] - fn has_signal_changed(&self, signal_ref: SignalRef) -> bool { - let byte = signal_ref.index() / 8; - let bit = signal_ref.index() % 8; + fn has_signal_changed(&self, vec_id: GhwVecId) -> bool { + let byte = vec_id.index() / 8; + let bit = vec_id.index() % 8; (self.signal_change[byte] >> bit) & 1 == 1 } #[inline] - fn mark_signal_changed(&mut self, signal_ref: SignalRef) { - let byte = signal_ref.index() / 8; - let bit = signal_ref.index() % 8; + fn mark_signal_changed(&mut self, vec_id: GhwVecId) { + let byte = vec_id.index() / 8; + let bit = vec_id.index() % 8; self.signal_change[byte] |= 1u8 << bit; - self.change_list.push(signal_ref); + self.change_list.push(vec_id); } #[inline] @@ -443,8 +408,8 @@ impl VecBuffer { fn get_data_index(bits: u32, bit: u32, states: States) -> (usize, usize) { debug_assert!(bit < bits); let mirrored = bits - 1 - bit; - let index = mirrored as usize / states.bits_in_a_byte(); - let shift = (bit as usize % states.bits_in_a_byte()) * states.bits(); + let index = bit as usize / states.bits_in_a_byte(); + let shift = (mirrored as usize % states.bits_in_a_byte()) * states.bits(); (index, shift) } }