diff --git a/src/ghw/signals.rs b/src/ghw/signals.rs index 2dbe7ce..1dedc49 100644 --- a/src/ghw/signals.rs +++ b/src/ghw/signals.rs @@ -223,7 +223,7 @@ struct VecBufferInfo { bits: u32, states: States, signal_ref: SignalRef, - min_index: u32, + max_index: u32, } impl VecBufferInfo { @@ -261,7 +261,7 @@ impl VecBuffer { bits, states, signal_ref: vector.signal_ref(), - min_index: vector.min().index() as u32, + max_index: vector.max().index() as u32, }; data_start += (bits as usize).div_ceil(states.bits_in_a_byte()); bit_change_start += (bits as usize).div_ceil(8); @@ -299,14 +299,14 @@ impl VecBuffer { #[inline] fn is_second_change(&self, vector_id: GhwVecId, signal_id: GhwSignalId, value: u8) -> bool { let info = &self.info[vector_id.index()]; - let bit = signal_id.index() as u32 - info.min_index; + let bit = info.max_index - signal_id.index() as u32; self.has_bit_changed(info, bit) && self.get_value(info, bit) != value } #[inline] fn update_value(&mut self, vector_id: GhwVecId, signal_id: GhwSignalId, value: u8) { let info = &self.info[vector_id.index()]; - let bit = signal_id.index() as u32 - info.min_index; + let bit = info.max_index - signal_id.index() as u32; 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); @@ -395,30 +395,76 @@ impl VecBuffer { self.change_list.push(vec_id); } - #[inline] fn get_value(&self, info: &VecBufferInfo, bit: u32) -> u8 { debug_assert!(bit < info.bits); let data = &self.data[info.data_range()]; - let (index, shift) = Self::get_data_index(info.bits, bit, info.states); - let byte = data[index]; - (byte >> shift) & info.states.mask() + // specialize depending on states + match info.states { + States::Two => get_value(info.bits, States::Two, data, bit), + States::Four => get_value(info.bits, States::Four, data, bit), + States::Nine => get_value(info.bits, States::Nine, data, bit), + } } #[inline] fn set_value(data: &mut [u8], info: &VecBufferInfo, bit: u32, value: u8) { debug_assert!(value <= 0xf); - let (index, shift) = Self::get_data_index(info.bits, bit, info.states); - let data = &mut data[info.data_range()][index..(index + 1)]; - let old_data = data[0] & !(info.states.mask() << shift); - data[0] = old_data | (value << shift); + let data = &mut data[info.data_range()]; + // specialize depending on states + match info.states { + States::Two => set_value(info.bits, States::Two, data, bit, value), + States::Four => set_value(info.bits, States::Four, data, bit, value), + States::Nine => set_value(info.bits, States::Nine, data, bit, value), + } } +} - #[inline] - fn get_data_index(bits: u32, bit: u32, states: States) -> (usize, usize) { - debug_assert!(bit < bits); - let mirrored = bits - 1 - bit; - let index = bit as usize / states.bits_in_a_byte(); - let shift = (mirrored as usize % states.bits_in_a_byte()) * states.bits(); - (index, shift) +#[inline] +fn get_value(bits: u32, states: States, data: &[u8], bit: u32) -> u8 { + debug_assert!(bit < bits); + let (index, shift) = get_data_index(bits, bit, states); + let byte = data[index]; + (byte >> shift) & states.mask() +} + +#[inline] +fn set_value(bits: u32, states: States, data: &mut [u8], bit: u32, value: u8) { + debug_assert!(value <= 0xf); + let (index, shift) = get_data_index(bits, bit, states); + let data = &mut data[index..(index + 1)]; + let old_data = data[0] & !(states.mask() << shift); + data[0] = old_data | (value << shift); +} + +#[inline] +fn get_data_index(bits: u32, bit: u32, states: States) -> (usize, usize) { + debug_assert!(bit < bits); + let bytes = bits.div_ceil(states.bits_in_a_byte() as u32); + let mirrored = (bytes * states.bits_in_a_byte() as u32) - 1 - bit; + let index = mirrored as usize / states.bits_in_a_byte(); + let shift = (bit as usize % states.bits_in_a_byte()) * states.bits(); + (index, shift) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_get_data_index() { + // big endian and right aligned + assert_eq!(get_data_index(4, 0, States::Nine), (1, 0)); + assert_eq!(get_data_index(4, 1, States::Nine), (1, 4)); + assert_eq!(get_data_index(4, 2, States::Nine), (0, 0)); + assert_eq!(get_data_index(4, 3, States::Nine), (0, 4)); + + assert_eq!(get_data_index(3, 0, States::Nine), (1, 0)); + assert_eq!(get_data_index(3, 1, States::Nine), (1, 4)); + assert_eq!(get_data_index(3, 2, States::Nine), (0, 0)); + + assert_eq!(get_data_index(4, 0, States::Two), (0, 0)); + assert_eq!(get_data_index(4, 1, States::Two), (0, 1)); + assert_eq!(get_data_index(4, 2, States::Two), (0, 2)); + assert_eq!(get_data_index(4, 3, States::Two), (0, 3)); } } diff --git a/src/wavemem.rs b/src/wavemem.rs index d1760b4..c24a28d 100644 --- a/src/wavemem.rs +++ b/src/wavemem.rs @@ -301,6 +301,9 @@ fn load_fixed_len_signal( out.push(meta_data); out.append(&mut buf); } else { + if meta_data > 0 { + debug_assert_eq!(buf[0] & 0x3f, buf[0], "unexpected data in upper 2-bits of buf[0]={:x} {_signal_id:?} {len} {signal_states:?}", buf[0]); + } out.push(meta_data | buf[0]); out.extend_from_slice(&buf[1..]); } @@ -701,6 +704,7 @@ impl SignalEncoder { let bits = len.get(); if bits == 1 { debug_assert_eq!(value.len(), 1); + debug_assert!(value[0] <= 0xf); let write_value = ((time_idx_delta as u64) << 4) + value[0] as u64; leb128::write::unsigned(&mut self.data, write_value).unwrap(); } else { @@ -714,12 +718,29 @@ impl SignalEncoder { // write time and meta data let time_and_meta = (time_idx_delta as u64) << 2 | (min_states as u64); leb128::write::unsigned(&mut self.data, time_and_meta).unwrap(); + let data_start_index = self.data.len(); if min_states == states { // raw data self.data.extend_from_slice(value); } else { compress(value, states, min_states, bits as usize, &mut self.data); } + + // make sure the leading bits are 0 + if cfg!(debug_assertions) { + let first_byte = self.data[data_start_index]; + let bits_in_first_byte = (bits * min_states.bits() as u32) % 8; + let first_byte_mask = if bits_in_first_byte > 0 { + (1u8 << bits_in_first_byte) - 1 + } else { + 0xff + }; + debug_assert_eq!( + first_byte & first_byte_mask, + first_byte, + "{first_byte:x} & {first_byte_mask:x} {bits} {min_states:?}\n{value:?}" + ); + } } } other => unreachable!("Cannot call add_n_bit_change on signal of type: {other:?}"),