CIRCT 22.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) : offset(offset), numSteps(1) {}
38 /// Offset within the buffer in number of elements
39 uint32_t offset;
40 /// Number of time steps to advance at the given offset
41 uint32_t numSteps;
42};
43
44/// A heap allocated buffer containing raw trace data and time step markers
46
47public:
48 TraceBuffer() = delete;
49 explicit TraceBuffer(uint32_t capacity) : capacity(capacity) {
50 storage = std::make_unique<uint64_t[]>(capacity + 1);
52 }
53
54 // Never copy a trace buffer
55 TraceBuffer(const TraceBuffer &other) = delete;
56 TraceBuffer operator=(const TraceBuffer &other) = delete;
57
58 TraceBuffer(TraceBuffer &&other) noexcept = default;
59 TraceBuffer &operator=(TraceBuffer &&other) noexcept = default;
60
61 /// Available storage in number of elements.
62 /// Note: Actual capacity is +1 for sentinel
63 uint32_t capacity;
64 /// Number of valid elements, set on dispatch
65 uint32_t size = 0;
66 /// Time step of the buffer's first entry
67 int64_t firstStep = -1;
68 /// Time step markers
69 std::vector<TraceBufferMarker> stepMarkers;
70
71 /// Get the pointer to the buffer's storage
72 uint64_t *getData() const { return storage.get(); }
73
74 /// Reset the buffer
75 void clear() {
76 size = 0;
77 firstStep = -1;
78 stepMarkers.clear();
79 }
80
81 /// Assert that the buffer's sentinel value has not been overwritten
82 void assertSentinel() const {
84 impl::fatalError("Trace buffer sentinel overwritten");
85 }
86
87private:
88 static constexpr uint64_t sentinelValue = UINT64_C(0xABCD1234EFBA8765);
89 std::unique_ptr<uint64_t[]> storage;
90};
91
92/// Abstract TraceEncoder managing trace buffers and the encoder thread
94public:
95 TraceEncoder() = delete;
96 /// Construct a trace encoder for the given model and the given number of
97 /// buffers. Initializes the state with the first buffer.
99 unsigned numBuffers, bool debug);
100
101 virtual ~TraceEncoder() = default;
102
103 /// Begin tracing
104 void run(ArcState *state);
105 /// Dispatch the currently active trace buffer containing `oldBufferSize`
106 /// valid entries to the encoder thread and return the storage of the
107 /// new active buffer.
108 /// Blocks execution until a new buffer is available.
109 uint64_t *dispatch(uint32_t oldBufferSize);
110 /// Signal the start of a new simulation time step
111 void step(const ArcState *state);
112 /// Stop tracing
113 void finish(const ArcState *state);
114
115 /// Number of trace buffers in rotation
116 const unsigned numBuffers;
117
118protected:
119 // Virtual methods to be implemented by encoder backends.
120
121 /// Set-up the encoder before starting the worker thread. May return `false`
122 /// to indicate failure. In this case, no worker thread will be created.
123 /// Called by the simulation thread.
124 virtual bool initialize(const ArcState *state) = 0;
125
126 /// Called by the worker thread before entering the encode loop
127 virtual void startUpWorker(){};
128 /// Encode the given trace buffer. Called by the worker thread.
129 virtual void encode(TraceBuffer &work){};
130 /// Called by the worker thread after leaving the encode loop
131 virtual void windDownWorker(){};
132 /// Finish trace encoding. Called by the simulation thread.
133 virtual void finalize(const ArcState *state){};
134
135 /// Metadata of the traced model
137 /// Debug mode flag
138 const bool debug;
139
140private:
141 /// The encoder thread's work loop
142 void workLoop();
143
144 void enqueueBuffer(TraceBuffer &&buffer);
146
147 /// Current simulation time step
148 int64_t timeStep;
149
150 /// Trace encoder worker thread. If empty, tracing is disabled.
151 std::optional<std::thread> worker;
152
153 /// Queue and synchronization primitives for buffers to be processed by the
154 /// encoder thread
156 std::condition_variable bufferQueueCv;
157 std::queue<TraceBuffer> bufferQueue;
158
159 /// Return stack and synchronization primitives for processed buffers
161 std::condition_variable availableBuffersCv;
162 std::vector<TraceBuffer> availableBuffers;
163
164 /// Flag signaling that no more buffers will be enqueued
165 std::atomic<bool> isFinished;
166
167 /// Trace buffer currently in use by the hardware model
169};
170
171/// Dummy encoder discarding all produced trace data
172class DummyTraceEncoder final : public TraceEncoder {
173public:
176
177 ~DummyTraceEncoder() override = default;
178
179protected:
180 bool initialize(const ArcState *state) override { return false; }
181};
182
183} // namespace circt::arc::runtime::impl
184
185#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.
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.
uint32_t offset
Offset within the buffer in number of elements.
uint32_t numSteps
Number of time steps to advance at the given offset.
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.