Skip to content

Commit

Permalink
actually track aliases
Browse files Browse the repository at this point in the history
  • Loading branch information
ekiwi committed Mar 5, 2024
1 parent 1489f3f commit 70c1b2c
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 20 deletions.
24 changes: 24 additions & 0 deletions src/ghw/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,8 @@ pub struct GhwVecInfo {
max: GhwSignalId,
min: GhwSignalId,
two_state: bool,
/// pointer to an alias list
alias: Option<NonZeroU32>,
}

impl GhwVecInfo {
Expand All @@ -300,6 +302,7 @@ impl GhwVecInfo {
min,
max,
two_state,
alias: None,
}
}
pub fn bits(&self) -> u32 {
Expand All @@ -314,6 +317,13 @@ impl GhwVecInfo {
pub fn max(&self) -> GhwSignalId {
self.max
}
pub fn alias(&self) -> Option<NonZeroU32> {
self.alias
}

pub fn set_alias(&mut self, alias: NonZeroU32) {
self.alias = Some(alias);
}
}

/// Specifies the signal type info that is needed in order to read it.
Expand Down Expand Up @@ -409,3 +419,17 @@ pub const STD_LOGIC_LUT: [u8; 9] = [5, 2, 0, 1, 3, 6, 7, 4, 8];

/// The order in which the two values appear in the BIT enum.
pub const VHDL_BIT_VALUES: [u8; 2] = [b'0', b'1'];

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_sizes() {
// We store 8-bytes per GHW signal to have the SignalRef mapping, type and vector info available.
// This is in comparison to ghwdump which stores at least two 8-bit pointers per signal.
assert_eq!(std::mem::size_of::<GhwSignalInfo>(), 8);

assert_eq!(std::mem::size_of::<GhwVecInfo>(), 16);
}
}
72 changes: 57 additions & 15 deletions src/ghw/hierarchy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -916,21 +916,20 @@ struct GhwSignals {
/// Used to define aliased signals in the `wellen` wavemem.
#[derive(Debug, Clone, Copy)]
struct AliasInfo {
max: u32,
min: u32,
msb: u32,
lsb: u32,
signal_ref: SignalRef,
next: Option<NonZeroU32>,
}

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,
signal_ref_count: 0,
vectors: vec![],
aliases: vec![],
}
}

Expand Down Expand Up @@ -964,6 +963,47 @@ impl GhwSignals {
id
}

fn find_or_add_alias(&mut self, vec_id: GhwVecId, msb: u32, lsb: u32) -> SignalRef {
// first we try to see if we can find an existing alias
if let Some(mut alias_id) = self.vectors[vec_id.index()].alias() {
loop {
let alias = self.aliases[alias_id.get() as usize - 1].clone();
if alias.msb == msb && alias.lsb == lsb {
return alias.signal_ref;
}
match alias.next {
Some(next) => alias_id = next,
None => {
// create new entry
let signal_ref = self.new_signal_ref();
let new_alias_id = self.aliases.len() + 1;
self.aliases.push(AliasInfo {
msb,
lsb,
signal_ref,
next: None,
});
self.aliases[alias_id.get() as usize - 1].next =
Some(NonZeroU32::new(new_alias_id as u32).unwrap());
return signal_ref;
}
}
}
} else {
// create entry
let signal_ref = self.new_signal_ref();
let alias_id = self.aliases.len() + 1;
self.aliases.push(AliasInfo {
msb,
lsb,
signal_ref,
next: None,
});
self.vectors[vec_id.index()].set_alias(NonZeroU32::new(alias_id as u32).unwrap());
signal_ref
}
}

fn register_bit_vec(
&mut self,
min_id: GhwSignalId,
Expand All @@ -974,16 +1014,18 @@ impl GhwSignals {
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 maybe_vector_id = self.find_vec(min, max);
if let Some(vector_id) = maybe_vector_id {
let vector = &self.vectors[vector_id.index()];
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
// 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 {
} else if prev_min <= min && prev_max >= max {
// this means that a larger vector already exists and our signal is a slice of this vector
let (msb, lsb) = (max - prev_min, min - prev_min);
self.find_or_add_alias(vector_id, msb as u32, lsb as u32)
} else if prev_min >= min && prev_max <= max {
todo!("super signal alias!")
} else {
todo!("overlapped aliased vectors")
Expand Down
2 changes: 1 addition & 1 deletion src/ghw/signals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ 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| {
todo!("finish timestep with vec_id!");
todo!("finish timestep with vec_id! {signal_ref:?}");
// enc.raw_value_change(signal_ref, data, states);
})
}
Expand Down
10 changes: 6 additions & 4 deletions src/wavemem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -696,14 +696,16 @@ impl SignalEncoder {
match self.tpe {
SignalType::BitVector(len, _) => {
let bits = len.get();
debug_assert_eq!(
value.len(),
(bits as usize).div_ceil(states.bits_in_a_byte())
);
if bits == 1 {
debug_assert_eq!(value.len(), 1);
let write_value = ((time_idx_delta as u64) << 4) + value[0] as u64;
leb128::write::unsigned(&mut self.data, write_value).unwrap();
} else {
// sometimes we might include some leading zeros that are not necessary
let required_bytes = (bits as usize).div_ceil(states.bits_in_a_byte());
debug_assert!(value.len() >= required_bytes);
let value = &value[(value.len() - required_bytes)..];

// we automatically compress the signal to its minimum states encoding
let min_states = check_min_state(value, states);
// write time and meta data
Expand Down

0 comments on commit 70c1b2c

Please sign in to comment.