Skip to main content

rustdv_sim/
time.rs

1//! Simulation time (design-doc §3.1: time as u64 steps + precision).
2
3use rustdv_gpi as gpi;
4
5/// A span of simulation time in simulator precision steps. Unit-safe
6/// constructors (mapping row 13): `SimDuration::ns(2)`.
7#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
8pub struct SimDuration {
9    pub steps: u64,
10}
11
12impl SimDuration {
13    pub fn steps(steps: u64) -> SimDuration {
14        SimDuration { steps }
15    }
16
17    fn from_pow10(n: u64, exp: i32) -> SimDuration {
18        let prec = gpi::time_precision();
19        if exp >= prec {
20            let factor = 10u64.pow((exp - prec) as u32);
21            SimDuration { steps: n * factor }
22        } else {
23            let div = 10u64.pow((prec - exp) as u32);
24            assert!(
25                n % div == 0,
26                "duration {n}e{exp} is below simulator precision 1e{prec}"
27            );
28            SimDuration { steps: n / div }
29        }
30    }
31
32    pub fn fs(n: u64) -> SimDuration {
33        Self::from_pow10(n, -15)
34    }
35    pub fn ps(n: u64) -> SimDuration {
36        Self::from_pow10(n, -12)
37    }
38    pub fn ns(n: u64) -> SimDuration {
39        Self::from_pow10(n, -9)
40    }
41    pub fn us(n: u64) -> SimDuration {
42        Self::from_pow10(n, -6)
43    }
44    pub fn ms(n: u64) -> SimDuration {
45        Self::from_pow10(n, -3)
46    }
47    pub fn sec(n: u64) -> SimDuration {
48        Self::from_pow10(n, 0)
49    }
50
51    /// Parse a cocotb-style unit name ("ns", "us", ...).
52    pub fn from_unit(n: u64, unit: &str) -> SimDuration {
53        match unit {
54            "fs" => Self::fs(n),
55            "ps" => Self::ps(n),
56            "ns" => Self::ns(n),
57            "us" => Self::us(n),
58            "ms" => Self::ms(n),
59            "s" | "sec" => Self::sec(n),
60            "step" | "steps" => Self::steps(n),
61            _ => panic!("unknown time unit '{unit}'"),
62        }
63    }
64}
65
66/// Current simulation time in precision steps.
67pub fn sim_time_steps() -> u64 {
68    gpi::sim_time_steps()
69}
70
71/// Current simulation time in nanoseconds (for log formatting).
72pub fn sim_time_ns() -> f64 {
73    let prec = gpi::time_precision();
74    let steps = gpi::sim_time_steps() as f64;
75    steps * 10f64.powi(prec + 9)
76}