1use itertools::izip;
5use rayon::prelude::*;
6use std::fmt::Debug;
7use wellen::{Signal, SignalRef, SignalValue, TimeTableIdx, simple::Waveform};
8
9#[derive(Debug, Clone)]
10pub struct SignalStats {
11 pub trans_count_doubled: u32,
13 pub clean_trans_count: u32,
14 pub glitch_trans_count: u32,
15 pub high_time: u32,
16 pub low_time: u32,
17 pub x_time: u32,
18 pub z_time: u32,
19}
20
21impl Default for SignalStats {
22 fn default() -> Self {
23 Self {
24 trans_count_doubled: 0,
25 clean_trans_count: 0,
26 glitch_trans_count: 0,
27 high_time: 0,
28 low_time: 0,
29 x_time: 0,
30 z_time: 0,
31 }
32 }
33}
34
35impl SignalStats {
36 fn modify_time_stat_of_value<'s, F>(&'s mut self, val: char, f: F)
37 where
38 F: FnOnce(u32) -> u32,
39 {
40 match val {
41 '1' => self.high_time = f(self.high_time),
42 '0' => self.low_time = f(self.low_time),
43 'x' => self.x_time = f(self.x_time),
44 'z' => self.z_time = f(self.z_time),
45 _ => panic!("Invalid value"),
46 }
47 }
48}
49
50impl SignalStats {
51 fn is_glitch<'s>(&'s mut self) -> bool {
52 self.clean_trans_count >= 2 || self.glitch_trans_count >= 2 || self.trans_count_doubled > 2
53 }
54}
55
56impl SignalStats {
57 fn clear<'s>(&'s mut self) {
58 self.trans_count_doubled = 0;
59 self.clean_trans_count = 0;
60 self.glitch_trans_count = 0;
61 self.high_time = 0;
62 self.low_time = 0;
63 self.x_time = 0;
64 self.z_time = 0;
65 }
66}
67
68fn val_at(ti: TimeTableIdx, sig: &Signal) -> SignalValue<'_> {
69 let offset = sig
70 .get_offset(ti)
71 .expect("Signal change timestamp should be valid");
72 return sig.get_value_at(&offset, 0);
73}
74
75fn time_value_at(wave: &Waveform, ti: TimeTableIdx) -> u64 {
76 let time_stamp = wave.time_table()[ti as usize];
77 return time_stamp;
78}
79
80pub fn calc_stats_for_each_time_span(
81 wave: &Waveform,
82 glitches_only: bool,
83 clk_signal: Option<SignalRef>,
84 sig_ref: SignalRef,
85 num_of_iterations: u64,
86) -> Vec<PackedStats> {
87 let mut stats = Vec::with_capacity(num_of_iterations as usize);
88 let time_span = (*wave
89 .time_table()
90 .last()
91 .expect("Waveform shouldn't be empty"))
92 / num_of_iterations;
93
94 stats.extend(
95 (0..num_of_iterations)
96 .into_par_iter()
97 .map(|index| {
98 let first_time_stamp = index * time_span;
99 let last_time_stamp = (index + 1) * time_span;
100 return calc_stats(
101 wave,
102 glitches_only,
103 clk_signal,
104 sig_ref,
105 first_time_stamp,
106 last_time_stamp,
107 );
108 })
109 .collect::<Vec<PackedStats>>(),
110 );
111
112 return stats;
113}
114
115pub fn calc_stats(
116 wave: &Waveform,
117 glitches_only: bool,
118 clk_signal: Option<SignalRef>,
119 sig_ref: SignalRef,
120 first_time_stamp: wellen::Time,
121 last_time_stamp: wellen::Time,
122) -> PackedStats {
123 let sig = wave.get_signal(sig_ref).unwrap();
124
125 let n = sig.time_indices().len();
126 if n == 0 {
127 return PackedStats::Vector(Vec::new());
128 }
129
130 let mut prev_val = val_at(
131 sig.get_first_time_idx()
132 .expect("Signal should have at least one value change"),
133 sig,
134 );
135
136 let bits = prev_val.bits();
137
138 let bit_len = if let Some(bit_len) = bits {
140 bit_len
141 } else {
142 return PackedStats::Vector(Vec::new());
144 };
145
146 let mut ss = Vec::<SignalStats>::with_capacity(bit_len as usize);
147 for _ in 0..bit_len {
149 ss.push(Default::default())
150 }
151
152 let mut current_value_entry_index: usize = 1;
153
154 while current_value_entry_index < sig.time_indices().len() {
156 let time_idx = sig.time_indices()[current_value_entry_index];
157
158 if time_value_at(wave, time_idx) > first_time_stamp {
159 break;
160 }
161
162 prev_val = val_at(time_idx, sig);
163
164 current_value_entry_index += 1;
165 }
166
167 let mut prev_ts = first_time_stamp;
169
170 while current_value_entry_index < sig.time_indices().len() {
172 let time_idx = sig.time_indices()[current_value_entry_index];
173 let val = val_at(time_idx, sig);
174 let ts = time_value_at(wave, time_idx);
175 current_value_entry_index += 1;
176
177 if ts > last_time_stamp {
178 break;
179 }
180
181 let val_str = val.to_bit_string().expect("Signal's value should be valid");
182 let prev_val_str = prev_val
183 .to_bit_string()
184 .expect("Signal's previous value should be valid");
185 for (c, prev_c, i) in izip!(val_str.chars(), prev_val_str.chars(), 0..) {
186 match (prev_c, c) {
187 ('0', '1') | ('1', '0') => {
188 ss[i].clean_trans_count += 1;
189 ss[i].trans_count_doubled += 2;
190 }
191 (other @ _, 'x') | ('x', other @ _) => {
192 if other != 'x' {
193 ss[i].trans_count_doubled += 1;
194 ss[i].glitch_trans_count += 1;
195 }
196 }
197 (other @ _, 'z') | ('z', other @ _) => {
198 if other != 'z' {
199 ss[i].trans_count_doubled += 1;
200 if other == '0' {
201 ss[i].clean_trans_count += 1;
202 }
203 }
204 }
205 _ => {
206 if prev_c != c {
207 panic!("Unknown transition {prev_c} -> {c}")
208 }
209 }
210 }
211
212 ss[i].modify_time_stat_of_value(prev_c, |v| v + (ts - prev_ts) as u32);
213 }
214 prev_ts = ts;
215 prev_val = val;
216 }
217
218 for (prev_c, i) in izip!(
219 prev_val
220 .to_bit_string()
221 .expect("Signal's previous value should be valid")
222 .chars(),
223 0..
224 ) {
225 ss[i]
226 .modify_time_stat_of_value(prev_c, |v| v + (last_time_stamp - (prev_ts as u64)) as u32);
227 }
228
229 if glitches_only {
230 for stat in ss.iter_mut() {
231 if !stat.is_glitch() || (clk_signal != None && sig_ref == clk_signal.unwrap()) {
232 stat.clear();
233 }
234 }
235 }
236
237 ss.reverse();
239
240 return if ss.len() == 1 {
241 PackedStats::OneBit(
242 ss.into_iter()
243 .next()
244 .expect("Signal's value should be valid"),
245 )
246 } else {
247 PackedStats::Vector(ss)
248 };
249}
250
251pub fn empty_stats(wave: &Waveform, sig_ref: SignalRef) -> PackedStats {
252 let sig = wave.get_signal(sig_ref).unwrap();
253
254 if sig.time_indices().len() == 0 {
255 return PackedStats::Vector(Vec::new());
256 }
257
258 let bits = val_at(
259 sig.get_first_time_idx()
260 .expect("Signal should have at least one value change"),
261 sig,
262 )
263 .bits();
264
265 let bit_len: usize = if let Some(bit_len) = bits {
267 bit_len as usize
268 } else {
269 return PackedStats::Vector(Vec::new());
271 };
272
273 let ss = vec![Default::default(); bit_len];
274
275 return if ss.len() == 1 {
276 PackedStats::OneBit(
277 ss.into_iter()
278 .next()
279 .expect("Signal's value should be valid"),
280 )
281 } else {
282 PackedStats::Vector(ss)
283 };
284}
285
286#[derive(Clone)]
287pub enum PackedStats {
288 OneBit(SignalStats),
289 Vector(Vec<SignalStats>),
290}