use crate::{BaseTimer, Delta, TArch, TDesc, TraceValue};
#[derive(Debug, Clone, Copy)]
pub struct Trace<const S: bool, T: TraceValue, const N: usize>
where
TDesc<S>: TArch,
{
base: BaseTimer<S>,
index: usize,
trace: [T; N],
}
impl<const S: bool, T, const N: usize> std::default::Default for Trace<S, T, N>
where
TDesc<S>: TArch,
T: TraceValue,
[T; N]: Default,
{
fn default() -> Self {
let base = BaseTimer::default();
let index = 0;
let trace = <[T; N]>::default();
Self { base, index, trace }
}
}
impl<const S: bool, T, const N: usize> Trace<S, T, N>
where
TDesc<S>: TArch,
T: TraceValue,
{
pub fn clear(&mut self) {
unsafe { *self = std::mem::zeroed() };
}
#[inline(always)]
pub fn start(&mut self) {
self.base.start();
self.index = 0;
}
#[inline(always)]
pub fn next(&mut self) {
if self.index < N {
let delta = self.base.elapsed_delta_and_update();
self.trace[self.index] = delta.into();
self.index += 1;
}
}
pub fn trace(&self) -> &[T; N] {
&self.trace
}
}
#[derive(Debug, Clone, Copy)]
pub struct AccTrace<const S: bool, T: TraceValue, const N: usize>
where
TDesc<S>: TArch,
{
trace: Trace<S, T, N>,
acc: [T; N],
}
impl<const S: bool, T, const N: usize> std::default::Default for AccTrace<S, T, N>
where
TDesc<S>: TArch,
T: TraceValue,
[T; N]: Default,
{
fn default() -> Self {
let trace = Trace::default();
let acc = <[T; N]>::default();
Self { trace, acc }
}
}
impl<const S: bool, T, const N: usize> AccTrace<S, T, N>
where
TDesc<S>: TArch,
T: TraceValue,
{
pub fn clear(&mut self) {
self.trace.clear();
unsafe { self.acc = std::mem::zeroed() };
}
#[inline(always)]
pub fn start(&mut self) {
self.trace.start();
}
#[inline(always)]
pub fn next(&mut self) {
self.trace.next();
}
pub fn acc(&mut self) {
for i in 0..N {
let v: Delta = self.acc[i].into();
let v = v.add(self.trace.trace[i].into());
self.acc[i] = v.into();
}
}
pub fn last_trace(&self) -> &[T; N] {
self.trace.trace()
}
pub fn acc_trace(&self) -> &[T; N] {
&self.acc
}
}