CIRCT 23.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
Dummy encoder discarding all produced trace data.
bool initialize(const ArcState *state) override
Set-up the encoder before starting the worker thread.
DummyTraceEncoder(const ArcRuntimeModelInfo *modelInfo, ArcState *state)
Abstract TraceEncoder managing trace buffers and the encoder thread.
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.
const bool debug
Debug mode flag.
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
Helper for marking time steps within a trace buffer.
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.