Skip to main content

rhdl_ed25519_scalable_core/ubft/
latency.rs

1//! Isolated-request latency counters ([`Latency`]) and their register words.
2
3use super::*;
4
5/// Isolated-request latency statistics, in cycles.
6#[derive(Clone, Copy, Debug, PartialEq, Digital, Default)]
7pub struct Latency {
8    /// A measurement is open.
9    pub open: bool,
10    /// Its start tick.
11    pub start: b64,
12    /// Measurements taken.
13    pub n: b32,
14    /// The last one.
15    pub last: b32,
16    /// The smallest.
17    pub min: b32,
18    /// The largest.
19    pub max: b32,
20    /// Their sum.
21    pub sum: b64,
22}
23
24/// Opens or closes a latency measurement (DSig's rule): `begin` when a
25/// request is taken with none in flight, `end` when an answer's last beat
26/// leaves with one in flight, `abandon` when a second request arrives.
27#[kernel]
28pub fn latency_kernel(l: Latency, ticks: b64, begin: bool, end: bool, abandon: bool) -> Latency {
29    let mut n = l;
30    if end && l.open {
31        let sample: b32 = (ticks - l.start).resize();
32        n.open = false;
33        n.n = l.n + b32(1);
34        n.last = sample;
35        n.min = if l.n == b32(0) || sample < l.min { sample } else { l.min };
36        n.max = if sample > l.max { sample } else { l.max };
37        n.sum = l.sum + sample.resize::<64>();
38    }
39    if abandon {
40        n.open = false;
41    }
42    if begin {
43        n.open = true;
44        n.start = ticks;
45    }
46    n
47}
48
49/// One register word of a latency block (`i` = 0 `N`, 1 `LAST`, 2 `MIN`,
50/// 3 `MAX`, 4 `SUM` lo, 5 `SUM` hi).
51#[kernel]
52pub fn latency_word(l: Latency, i: b3) -> b32 {
53    if i == b3(0) {
54        l.n
55    } else if i == b3(1) {
56        l.last
57    } else if i == b3(2) {
58        l.min
59    } else if i == b3(3) {
60        l.max
61    } else if i == b3(4) {
62        l.sum.resize()
63    } else {
64        (l.sum >> 32).resize()
65    }
66}