rhdl_ed25519_fast_core/simulation.rs
1//! Host-only, constant-memory cycle simulation without waveform recording.
2//!
3//! RHDL's `run_fn` records trace pages, which is useful for waveforms but costly
4//! for throughput experiments. This driver uses the **same** `Synchronous::sim`
5//! hardware transitions with tracing disabled. It is not a cryptographic model
6//! or a replacement for RTL simulation. One [`CycleSim::tick`] is one rising edge.
7
8use rhdl::prelude::*;
9
10/// A native RHDL simulator with no per-cycle history allocation.
11pub struct CycleSim<C: Synchronous> {
12 circuit: C,
13 state: C::S,
14 cycles: u64,
15}
16
17impl<C: Synchronous> CycleSim<C> {
18 /// Construct a simulator and apply one synchronous reset edge.
19 pub fn new(circuit: C) -> Self {
20 let state = circuit.init();
21 let mut sim = Self {
22 circuit,
23 state,
24 cycles: 0,
25 };
26 sim.edge(C::I::dont_care(), true);
27 sim
28 }
29
30 fn edge(&mut self, input: C::I, reset_high: bool) -> C::O {
31 for level in [false, true] {
32 let cr = rhdl::core::clock_reset(
33 rhdl::core::clock::clock(level),
34 rhdl::core::types::reset::reset(reset_high),
35 );
36 let output = self.circuit.sim(cr, input, &mut self.state);
37 if level {
38 return output;
39 }
40 }
41 unreachable!()
42 }
43
44 /// Advance one clock cycle; inputs must obey the circuit's ready/valid rules.
45 pub fn tick(&mut self, input: C::I) -> C::O {
46 self.cycles += 1;
47 self.edge(input, false)
48 }
49
50 /// Number of non-reset rising edges simulated so far.
51 pub fn cycles(&self) -> u64 {
52 self.cycles
53 }
54}