CIRCT 24.0.0git
Loading...
Searching...
No Matches
TraceEncoder.h
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Provides an abstract TraceEncoder class implementing the trace buffer
10// management and communication between the simulation thread and the trace
11// encoder thread.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef CIRCT_DIALECT_ARC_RUNTIME_TRACEENCODER_H
16#define CIRCT_DIALECT_ARC_RUNTIME_TRACEENCODER_H
17
20
21#include <atomic>
22#include <cassert>
23#include <condition_variable>
24#include <cstddef>
25#include <cstdint>
26#include <mutex>
27#include <optional>
28#include <queue>
29#include <thread>
30#include <vector>
31
33
34/// Helper for marking time steps within a trace buffer
37 explicit TraceBufferMarker(uint32_t offset, uint64_t simTime)
39 /// Offset within the buffer in number of elements
40 uint32_t offset;
41 /// Simulation time in femtoseconds at this marker
42 uint64_t simTime;
43 /// Number of time steps to advance at the given offset
44 uint32_t numSteps;
45};
46
47/// A heap allocated buffer containing raw trace data and time step markers
49
50public:
51 TraceBuffer() = delete;
52 explicit TraceBuffer(uint32_t capacity) : capacity(capacity) {
53 storage = std::make_unique<uint64_t[]>(capacity + 1);
55 }
56
57 // Never copy a trace buffer
58 TraceBuffer(const TraceBuffer &other) = delete;
59 TraceBuffer operator=(const TraceBuffer &other) = delete;
60
61 TraceBuffer(TraceBuffer &&other) noexcept = default;
62 TraceBuffer &operator=(TraceBuffer &&other) noexcept = default;
63
64 /// Available storage in number of elements.
65 /// Note: Actual capacity is +1 for sentinel
66 uint32_t capacity;
67 /// Number of valid elements, set on dispatch
68 uint32_t size = 0;
69 /// Time step of the buffer's first entry
70 int64_t firstStep = -1;
71 /// Simulation time in femtoseconds at the buffer's first entry
72 uint64_t firstSimTime = 0;
73 /// Time step markers
74 std::vector<TraceBufferMarker> stepMarkers;
75
76 /// Get the pointer to the buffer's storage
77 uint64_t *getData() const { return storage.get(); }
78
79 /// Reset the buffer
80 void clear() {
81 size = 0;
82 firstStep = -1;
83 firstSimTime = 0;
84 stepMarkers.clear();
85 }
86
87 /// Assert that the buffer's sentinel value has not been overwritten
88 void assertSentinel() const {
90 impl::fatalError("Trace buffer sentinel overwritten");
91 }
92
93private:
94 static constexpr uint64_t sentinelValue = UINT64_C(0xABCD1234EFBA8765);
95 std::unique_ptr<uint64_t[]> storage;
96};
97
98/// Abstract TraceEncoder managing trace buffers and the encoder thread
100public:
101 TraceEncoder() = delete;
102 /// Construct a trace encoder for the given model and the given number of
103 /// buffers. Initializes the state with the first buffer.
105 unsigned numBuffers, bool debug);
106
107 virtual ~TraceEncoder() = default;
108
109 /// Begin tracing
110 void run(ArcState *state);
111 /// Dispatch the currently active trace buffer containing `oldBufferSize`
112 /// valid entries to the encoder thread and return the storage of the
113 /// new active buffer.
114 /// Blocks execution until a new buffer is available.
115 uint64_t *dispatch(uint32_t oldBufferSize);
116 /// Signal the start of a new simulation time step
117 void step(const ArcState *state);
118 /// Stop tracing
119 void finish(const ArcState *state);
120
121 /// Return the value of the internal step counter
122 int64_t getTimeStep() const { return timeStep; }
123
124 /// Number of trace buffers in rotation
125 const unsigned numBuffers;
126
127protected:
128 // Virtual methods to be implemented by encoder backends.
129
130 /// Set-up the encoder before starting the worker thread. May return `false`
131 /// to indicate failure. In this case, no worker thread will be created.
132 /// Called by the simulation thread.
133 virtual bool initialize(const ArcState *state) = 0;
134
135 /// Called by the worker thread before entering the encode loop
136 virtual void startUpWorker() {}
137 /// Encode the given trace buffer. Called by the worker thread.
138 virtual void encode(TraceBuffer &work) {}
139 /// Called by the worker thread after leaving the encode loop
140 virtual void windDownWorker() {}
141 /// Finish trace encoding. Called by the simulation thread.
142 virtual void finalize(const ArcState *state) {}
143
144 /// Metadata of the traced model
146 /// Debug mode flag
147 const bool debug;
148
149private:
150 /// The encoder thread's work loop
151 void workLoop();
152
153 void enqueueBuffer(TraceBuffer &&buffer);
155
156 /// Current simulation time step
157 int64_t timeStep;
158 /// Current simulation time in femtoseconds
159 uint64_t simTime;
160
161 /// Trace encoder worker thread. If empty, tracing is disabled.
162 std::optional<std::thread> worker;
163
164 /// Queue and synchronization primitives for buffers to be processed by the
165 /// encoder thread
167 std::condition_variable bufferQueueCv;
168 std::queue<TraceBuffer> bufferQueue;
169
170 /// Return stack and synchronization primitives for processed buffers
172 std::condition_variable availableBuffersCv;
173 std::vector<TraceBuffer> availableBuffers;
174
175 /// Flag signaling that no more buffers will be enqueued
176 std::atomic<bool> isFinished;
177
178 /// Trace buffer currently in use by the hardware model
180};
181
182/// Dummy encoder discarding all produced trace data
183class DummyTraceEncoder final : public TraceEncoder {
184public:
187
188 ~DummyTraceEncoder() override = default;
189
190protected:
191 bool initialize(const ArcState *state) override { return false; }
192};
193
194} // namespace circt::arc::runtime::impl
195
196#endif // CIRCT_DIALECT_ARC_RUNTIME_TRACEENCODER_H
bool initialize(const ArcState *state) override
Set-up the encoder before starting the worker thread.
DummyTraceEncoder(const ArcRuntimeModelInfo *modelInfo, ArcState *state)
virtual bool initialize(const ArcState *state)=0
Set-up the encoder before starting the worker thread.
std::atomic< bool > isFinished
Flag signaling that no more buffers will be enqueued.
std::queue< TraceBuffer > bufferQueue
virtual void startUpWorker()
Called by the worker thread before entering the encode loop.
uint64_t simTime
Current simulation time in femtoseconds.
int64_t getTimeStep() const
Return the value of the internal step counter.
void workLoop()
The encoder thread's work loop.
std::mutex bufferQueueMutex
Queue and synchronization primitives for buffers to be processed by the encoder thread.
virtual void finalize(const ArcState *state)
Finish trace encoding. Called by the simulation thread.
void step(const ArcState *state)
Signal the start of a new simulation time step.
std::mutex availableBuffersMutex
Return stack and synchronization primitives for processed buffers.
virtual void windDownWorker()
Called by the worker thread after leaving the encode loop.
virtual void encode(TraceBuffer &work)
Encode the given trace buffer. Called by the worker thread.
void run(ArcState *state)
Begin tracing.
std::condition_variable availableBuffersCv
const unsigned numBuffers
Number of trace buffers in rotation.
std::vector< TraceBuffer > availableBuffers
void enqueueBuffer(TraceBuffer &&buffer)
int64_t timeStep
Current simulation time step.
const ArcRuntimeModelInfo *const modelInfo
Metadata of the traced model.
TraceBuffer activeBuffer
Trace buffer currently in use by the hardware model.
std::condition_variable bufferQueueCv
void finish(const ArcState *state)
Stop tracing.
uint64_t * dispatch(uint32_t oldBufferSize)
Dispatch the currently active trace buffer containing oldBufferSize valid entries to the encoder thre...
std::optional< std::thread > worker
Trace encoder worker thread. If empty, tracing is disabled.
static void fatalError(const char *message)
Raise an irrecoverable error.
Definition Internal.h:23
Definition debug.py:1
Static information for a compiled hardware model, generated by the MLIR lowering.
Definition Common.h:70
Combined runtime and model state for a hardware model instance.
Definition Common.h:44
uint64_t simTime
Simulation time in femtoseconds at this marker.
uint32_t offset
Offset within the buffer in number of elements.
uint32_t numSteps
Number of time steps to advance at the given offset.
TraceBufferMarker(uint32_t offset, uint64_t simTime)
A heap allocated buffer containing raw trace data and time step markers.
TraceBuffer(const TraceBuffer &other)=delete
TraceBuffer(TraceBuffer &&other) noexcept=default
int64_t firstStep
Time step of the buffer's first entry.
std::unique_ptr< uint64_t[]> storage
std::vector< TraceBufferMarker > stepMarkers
Time step markers.
TraceBuffer & operator=(TraceBuffer &&other) noexcept=default
uint32_t size
Number of valid elements, set on dispatch.
void assertSentinel() const
Assert that the buffer's sentinel value has not been overwritten.
static constexpr uint64_t sentinelValue
uint64_t * getData() const
Get the pointer to the buffer's storage.
TraceBuffer operator=(const TraceBuffer &other)=delete
uint32_t capacity
Available storage in number of elements.
uint64_t firstSimTime
Simulation time in femtoseconds at the buffer's first entry.