Loop Timing Witness
Native controller and runtime interfaces; hardware qualification pending
Loading...
Searching...
No Matches
simulation.h
Go to the documentation of this file.
1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Commercial license available
3// © Concepts 1996–2026 Miroslav Šotek. All rights reserved.
4// © Code 2020–2026 Miroslav Šotek. All rights reserved.
5// ORCID: 0009-0009-3560-0851
6// Contact: www.anulum.li | protoscience@anulum.li
7// Loop Timing Witness — reusable production RTL clock and AXI transport
8
12
13#ifndef WITNESS_SIMULATION_H
14#define WITNESS_SIMULATION_H
15
16#include "Vaxi_control_witness.h"
17#include "../refusal.h"
18#include "verilated.h"
19#include <cstdint>
20#include <stdexcept>
21
22namespace witness {
24constexpr std::uint64_t transaction_limit = 100000;
25
27struct Edge {
28 bool aw, w, ar, b, r;
29 unsigned response;
30 std::uint32_t data;
31};
32
35 VerilatedContext context;
36 Vaxi_control_witness model{&context};
37
39 Edge tick() {
40 model.eval();
41 context.timeInc(1);
42 const bool bus_edge = context.time() % 7 == 0;
43 const bool capture_edge = context.time() % 5 == 0;
44 const bool rising = bus_edge && !model.bus_clock;
45 const Edge edge{rising && model.awvalid && model.awready,
46 rising && model.wvalid && model.wready,
47 rising && model.arvalid && model.arready,
48 rising && model.bvalid && model.bready,
49 rising && model.rvalid && model.rready,
50 model.rvalid ? model.rresp : model.bresp,
51 model.rdata};
52 if (bus_edge)
53 model.bus_clock = !model.bus_clock;
54 if (capture_edge)
55 model.capture_clock = !model.capture_clock;
56 if (bus_edge || capture_edge)
57 model.eval();
58 if (context.gotFinish())
59 throw witness::RuntimeRefused("RTL ended during transaction");
60 return edge;
61 }
62
63 public:
66 model.run_reset_n = 0;
67 model.eval();
68 advance(140);
69 model.run_reset_n = 1;
70 advance(140);
71 }
72
74 ~Simulation() { model.final(); }
75
77 std::uint64_t time() const { return context.time(); }
78
80 void advance(std::uint64_t nanoseconds) {
81 for (std::uint64_t index = 0; index < nanoseconds; ++index)
82 tick();
83 }
84
86 Edge read(std::uint8_t address) {
87 model.araddr = address;
88 model.arvalid = 1;
89 model.rready = 1;
90 for (std::uint64_t index = 0; index < transaction_limit; ++index) {
91 const Edge edge = tick();
92 if (edge.ar)
93 model.arvalid = 0;
94 if (edge.r) {
95 model.rready = 0;
96 return edge;
97 }
98 }
99 throw witness::RuntimeRefused("AXI read timed out");
100 }
101
103 Edge write(std::uint8_t address, std::uint32_t data, std::uint8_t strobes) {
104 model.awaddr = address;
105 model.wdata = data;
106 model.wstrb = strobes;
107 model.awvalid = 1;
108 model.wvalid = 1;
109 model.bready = 1;
110 for (std::uint64_t index = 0; index < transaction_limit; ++index) {
111 const Edge edge = tick();
112 if (edge.aw)
113 model.awvalid = 0;
114 if (edge.w)
115 model.wvalid = 0;
116 if (edge.b) {
117 model.bready = 0;
118 return edge;
119 }
120 }
121 throw witness::RuntimeRefused("AXI write timed out");
122 }
123
125 bool wait_interrupt(std::uint64_t nanoseconds) {
126 for (std::uint64_t index = 0; index < nanoseconds && !model.interrupt_line; ++index)
127 tick();
128 return model.interrupt_line;
129 }
130};
131
132} // namespace witness
133
155
156#endif
std::uint64_t time() const
Definition simulation.h:77
Edge write(std::uint8_t address, std::uint32_t data, std::uint8_t strobes)
Definition simulation.h:103
Edge read(std::uint8_t address)
Definition simulation.h:86
bool wait_interrupt(std::uint64_t nanoseconds)
Definition simulation.h:125
void advance(std::uint64_t nanoseconds)
Definition simulation.h:80
constexpr std::uint64_t transaction_limit
Definition simulation.h:24
unsigned response
Definition simulation.h:29
std::uint32_t data
Definition simulation.h:30