esiaccel 0.1.5.dev347__cp310-cp310-win_amd64.whl → 0.2.3.dev80__cp310-cp310-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- esiaccel/CosimBackend.dll +0 -0
- esiaccel/CosimBackend.lib +0 -0
- esiaccel/CosimRpc.dll +0 -0
- esiaccel/CosimRpc.lib +0 -0
- esiaccel/ESICppRuntime.dll +0 -0
- esiaccel/ESICppRuntime.lib +0 -0
- esiaccel/EsiCosimDpiServer.dll +0 -0
- esiaccel/EsiCosimDpiServer.lib +0 -0
- esiaccel/MtiPli.dll +0 -0
- esiaccel/MtiPli.lib +0 -0
- esiaccel/__init__.py +12 -3
- esiaccel/abseil_dll.dll +0 -0
- esiaccel/accelerator.py +37 -5
- esiaccel/cares.dll +0 -0
- esiaccel/cmake/esiaccelConfig.cmake +34 -0
- esiaccel/codegen.py +3 -3
- esiaccel/cosim/Cosim_CycleCount.sv +84 -0
- esiaccel/cosim/simulator.py +1 -0
- esiaccel/esiCppAccel.cp312-win_amd64.pyd +0 -0
- esiaccel/esiquery.exe +0 -0
- esiaccel/include/esi/Accelerator.h +14 -17
- esiaccel/include/esi/CLI.h +5 -5
- esiaccel/include/esi/Common.h +6 -0
- esiaccel/include/esi/Context.h +17 -9
- esiaccel/include/esi/Design.h +9 -4
- esiaccel/include/esi/Ports.h +230 -23
- esiaccel/include/esi/Services.h +64 -18
- esiaccel/include/esi/Types.h +61 -0
- esiaccel/include/esi/backends/Cosim.h +5 -12
- esiaccel/include/esi/backends/RpcClient.h +97 -0
- esiaccel/include/esi/backends/RpcServer.h +21 -3
- esiaccel/libcrypto-3-x64.dll +0 -0
- esiaccel/libprotobuf.dll +0 -0
- esiaccel/libssl-3-x64.dll +0 -0
- esiaccel/re2.dll +0 -0
- esiaccel/types.py +6 -4
- esiaccel/zlib1.dll +0 -0
- {esiaccel-0.1.5.dev347.dist-info → esiaccel-0.2.3.dev80.dist-info}/METADATA +1 -1
- esiaccel-0.2.3.dev80.dist-info/RECORD +58 -0
- esiaccel/esiCppAccel.cp310-win_amd64.pyd +0 -0
- esiaccel-0.1.5.dev347.dist-info/RECORD +0 -54
- {esiaccel-0.1.5.dev347.dist-info → esiaccel-0.2.3.dev80.dist-info}/WHEEL +0 -0
- {esiaccel-0.1.5.dev347.dist-info → esiaccel-0.2.3.dev80.dist-info}/entry_points.txt +0 -0
- {esiaccel-0.1.5.dev347.dist-info → esiaccel-0.2.3.dev80.dist-info}/licenses/LICENSE +0 -0
- {esiaccel-0.1.5.dev347.dist-info → esiaccel-0.2.3.dev80.dist-info}/top_level.txt +0 -0
esiaccel/include/esi/Ports.h
CHANGED
|
@@ -35,13 +35,81 @@ using PortMap = std::map<std::string, ChannelPort &>;
|
|
|
35
35
|
/// but used by higher level APIs which add types.
|
|
36
36
|
class ChannelPort {
|
|
37
37
|
public:
|
|
38
|
-
ChannelPort(const Type *type)
|
|
38
|
+
ChannelPort(const Type *type);
|
|
39
39
|
virtual ~ChannelPort() {}
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
struct ConnectOptions {
|
|
42
|
+
/// The buffer size is optional and should be considered merely a hint.
|
|
43
|
+
/// Individual implementations use it however they like. The unit is number
|
|
44
|
+
/// of messages of the port type.
|
|
45
|
+
std::optional<unsigned> bufferSize = std::nullopt;
|
|
46
|
+
|
|
47
|
+
/// If the type of this port is a window, translate the incoming/outgoing
|
|
48
|
+
/// data into its underlying ('into') type. For 'into' types without lists,
|
|
49
|
+
/// just re-arranges the data fields from the lowered type to the 'into'
|
|
50
|
+
/// type.
|
|
51
|
+
///
|
|
52
|
+
/// If this option is false, no translation is done and the data is
|
|
53
|
+
/// passed through as-is. Same is true for non-windowed types.
|
|
54
|
+
///
|
|
55
|
+
/// For messages with lists, only two types are supported:
|
|
56
|
+
/// 1) Parallel encoding includes any 'header' data with each frame. Said
|
|
57
|
+
/// header data is the same across all frames, so this encoding is
|
|
58
|
+
/// inefficient but is commonly used for on-chip streaming interfaces.
|
|
59
|
+
/// Each frame contains a 'last' field to indicate the end of the list.
|
|
60
|
+
/// In cases where 'numItems' is greater than 1, a field named
|
|
61
|
+
/// '<listField>_size' indicates the number of valid items in that
|
|
62
|
+
/// frame.
|
|
63
|
+
/// 2) Serial (bulk transfer) encoding, where a 'header' frame precedes
|
|
64
|
+
/// the list data frame. Said header frame contains a 'count' field
|
|
65
|
+
/// indicating the number of items in the list. Importantly, the
|
|
66
|
+
/// header frame is always re-transmitted after the specified number of
|
|
67
|
+
/// list items have been sent. If the 'count' field is zero, the end of
|
|
68
|
+
/// the list has been reached. If it is non-zero, the message has not
|
|
69
|
+
/// been completely transmitted and reading should continue until a
|
|
70
|
+
/// 'count' of zero is received.
|
|
71
|
+
///
|
|
72
|
+
/// In both cases, the host-side MessageData contains the complete header
|
|
73
|
+
/// followed by the list data. In other words, header data is not duplicated
|
|
74
|
+
/// in the returned message. So for a windowed type with header fields and
|
|
75
|
+
/// a list of (x,y) coordinates, the host memory layout would be:
|
|
76
|
+
/// ```
|
|
77
|
+
/// struct ExampleList {
|
|
78
|
+
/// uint32_t headerField2; // SystemVerilog ordering
|
|
79
|
+
/// uint32_t headerField1;
|
|
80
|
+
/// size_t list_length; // Number list items
|
|
81
|
+
/// struct { uint16_t y, x; } list_data[];
|
|
82
|
+
/// }
|
|
83
|
+
/// ```
|
|
84
|
+
///
|
|
85
|
+
/// In a parallel encoding, each frame's wire format (from hardware) is:
|
|
86
|
+
/// ```
|
|
87
|
+
/// struct ExampleListFrame {
|
|
88
|
+
/// uint8_t list_last; // Non-zero indicates last item in list
|
|
89
|
+
/// struct { uint16_t y, x; } list_data[numItems]; // SV field ordering
|
|
90
|
+
/// uint32_t headerField2; // SV struct ordering (reversed)
|
|
91
|
+
/// uint32_t headerField1;
|
|
92
|
+
/// }
|
|
93
|
+
/// ```
|
|
94
|
+
///
|
|
95
|
+
/// Important note: for consistency, preserves SystemVerilog struct field
|
|
96
|
+
/// ordering! So it's the opposite of C struct ordering.
|
|
97
|
+
///
|
|
98
|
+
/// Implementation status:
|
|
99
|
+
/// - Only parallel list encoding is supported.
|
|
100
|
+
/// - Fields must be byte-aligned.
|
|
101
|
+
///
|
|
102
|
+
/// See the CIRCT documentation (or td files) for more details on windowed
|
|
103
|
+
/// messages.
|
|
104
|
+
bool translateMessage = true;
|
|
105
|
+
|
|
106
|
+
ConnectOptions(std::optional<unsigned> bufferSize = std::nullopt,
|
|
107
|
+
bool translateMessage = true)
|
|
108
|
+
: bufferSize(bufferSize), translateMessage(translateMessage) {}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/// Set up a connection to the accelerator.
|
|
112
|
+
virtual void connect(const ConnectOptions &options = ConnectOptions()) = 0;
|
|
45
113
|
virtual void disconnect() = 0;
|
|
46
114
|
virtual bool isConnected() const = 0;
|
|
47
115
|
|
|
@@ -64,13 +132,74 @@ public:
|
|
|
64
132
|
protected:
|
|
65
133
|
const Type *type;
|
|
66
134
|
|
|
135
|
+
/// Instructions for translating windowed types. Precomputes and optimizes a
|
|
136
|
+
/// list of copy operations.
|
|
137
|
+
struct TranslationInfo {
|
|
138
|
+
TranslationInfo(const WindowType *windowType) : windowType(windowType) {}
|
|
139
|
+
|
|
140
|
+
/// Precompute and optimize the copy operations for translating frames.
|
|
141
|
+
void precomputeFrameInfo();
|
|
142
|
+
|
|
143
|
+
/// The window type being translated.
|
|
144
|
+
const WindowType *windowType;
|
|
145
|
+
|
|
146
|
+
/// A copy operation for translating between frame data and the translation.
|
|
147
|
+
/// Run this during the translation.
|
|
148
|
+
struct CopyOp {
|
|
149
|
+
/// Offset in the incoming/outgoing frame data.
|
|
150
|
+
size_t frameOffset;
|
|
151
|
+
/// Offset in the translation buffer.
|
|
152
|
+
size_t bufferOffset;
|
|
153
|
+
/// Number of bytes to copy.
|
|
154
|
+
size_t size;
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
/// Information about a list field within a frame (for parallel encoding).
|
|
158
|
+
/// Note: Currently only numItems == 1 is supported (one list element per
|
|
159
|
+
/// frame).
|
|
160
|
+
struct ListFieldInfo {
|
|
161
|
+
/// Name of the list field.
|
|
162
|
+
std::string fieldName;
|
|
163
|
+
/// Offset of the list data array in the frame.
|
|
164
|
+
size_t dataOffset;
|
|
165
|
+
/// Size of each list element in bytes.
|
|
166
|
+
size_t elementSize;
|
|
167
|
+
/// Offset of the 'last' field in the frame.
|
|
168
|
+
size_t lastFieldOffset;
|
|
169
|
+
/// Offset in the translation buffer where list length is stored.
|
|
170
|
+
size_t listLengthBufferOffset;
|
|
171
|
+
/// Offset in the translation buffer where list data starts.
|
|
172
|
+
size_t listDataBufferOffset;
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
/// Information about each frame in the windowed type.
|
|
176
|
+
struct FrameInfo {
|
|
177
|
+
/// The total size of a frame in bytes.
|
|
178
|
+
size_t expectedSize;
|
|
179
|
+
/// Precomputed copy operations for translating this frame (non-list
|
|
180
|
+
/// fields).
|
|
181
|
+
std::vector<CopyOp> copyOps;
|
|
182
|
+
/// Information about list fields in this frame (parallel encoding).
|
|
183
|
+
/// Currently only one list field per frame is supported.
|
|
184
|
+
std::optional<ListFieldInfo> listField;
|
|
185
|
+
};
|
|
186
|
+
/// Precomputed information about each frame.
|
|
187
|
+
std::vector<FrameInfo> frames;
|
|
188
|
+
/// Size of the 'into' type in bytes (for fixed-size types).
|
|
189
|
+
/// For types with lists, this is the size of the fixed header portion.
|
|
190
|
+
size_t intoTypeBytes = 0;
|
|
191
|
+
/// True if the window contains a list field (variable-size message).
|
|
192
|
+
bool hasListField = false;
|
|
193
|
+
};
|
|
194
|
+
std::unique_ptr<TranslationInfo> translationInfo;
|
|
195
|
+
|
|
67
196
|
/// Method called by poll() to actually poll the channel if the channel is
|
|
68
197
|
/// connected.
|
|
69
198
|
virtual bool pollImpl() { return false; }
|
|
70
199
|
|
|
71
200
|
/// Called by all connect methods to let backends initiate the underlying
|
|
72
201
|
/// connections.
|
|
73
|
-
virtual void connectImpl(
|
|
202
|
+
virtual void connectImpl(const ConnectOptions &options) {}
|
|
74
203
|
};
|
|
75
204
|
|
|
76
205
|
/// A ChannelPort which sends data to the accelerator.
|
|
@@ -78,9 +207,11 @@ class WriteChannelPort : public ChannelPort {
|
|
|
78
207
|
public:
|
|
79
208
|
using ChannelPort::ChannelPort;
|
|
80
209
|
|
|
81
|
-
virtual void
|
|
82
|
-
|
|
83
|
-
|
|
210
|
+
virtual void connect(const ConnectOptions &options = {}) override {
|
|
211
|
+
translateMessages = options.translateMessage && translationInfo;
|
|
212
|
+
if (translateMessages)
|
|
213
|
+
translationInfo->precomputeFrameInfo();
|
|
214
|
+
connectImpl(options);
|
|
84
215
|
connected = true;
|
|
85
216
|
}
|
|
86
217
|
virtual void disconnect() override { connected = false; }
|
|
@@ -88,12 +219,72 @@ public:
|
|
|
88
219
|
|
|
89
220
|
/// A very basic blocking write API. Will likely change for performance
|
|
90
221
|
/// reasons.
|
|
91
|
-
|
|
222
|
+
void write(const MessageData &data) {
|
|
223
|
+
if (translateMessages) {
|
|
224
|
+
assert(translationBuffer.empty() &&
|
|
225
|
+
"Cannot call write() with pending translated messages");
|
|
226
|
+
translateOutgoing(data);
|
|
227
|
+
for (auto &msg : translationBuffer)
|
|
228
|
+
writeImpl(msg);
|
|
229
|
+
translationBuffer.clear();
|
|
230
|
+
} else {
|
|
231
|
+
writeImpl(data);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/// A basic non-blocking write API. Returns true if any of the data was queued
|
|
236
|
+
/// and/or sent. If the data type is a window a 'true' return does not
|
|
237
|
+
/// indicate that the message has been completely written. The 'flush' method
|
|
238
|
+
/// can be used to check that the entire buffer has been written. It is
|
|
239
|
+
/// invalid for backends to always return false (i.e. backends must eventually
|
|
240
|
+
/// ensure that writes may succeed).
|
|
241
|
+
bool tryWrite(const MessageData &data) {
|
|
242
|
+
if (translateMessages) {
|
|
243
|
+
// Do not accept a new message if there are pending messages to flush.
|
|
244
|
+
if (!flush())
|
|
245
|
+
return false;
|
|
246
|
+
assert(translationBuffer.empty() &&
|
|
247
|
+
"Translation buffer should be empty after successful flush");
|
|
248
|
+
translateOutgoing(data);
|
|
249
|
+
flush();
|
|
250
|
+
return true;
|
|
251
|
+
} else {
|
|
252
|
+
return tryWriteImpl(data);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
/// Flush any buffered data. Returns true if all data was flushed.
|
|
256
|
+
///
|
|
257
|
+
/// If `translateMessages` is false, calling `flush()` will immediately return
|
|
258
|
+
/// true and perform no action, as there is no buffered data to flush.
|
|
259
|
+
bool flush() {
|
|
260
|
+
while (translationBufferIdx < translationBuffer.size()) {
|
|
261
|
+
if (!tryWriteImpl(translationBuffer[translationBufferIdx]))
|
|
262
|
+
return false;
|
|
263
|
+
++translationBufferIdx;
|
|
264
|
+
}
|
|
265
|
+
translationBuffer.clear();
|
|
266
|
+
translationBufferIdx = 0;
|
|
267
|
+
return true;
|
|
268
|
+
}
|
|
92
269
|
|
|
93
|
-
|
|
94
|
-
///
|
|
95
|
-
|
|
96
|
-
|
|
270
|
+
protected:
|
|
271
|
+
/// Implementation for write(). Subclasses must implement this.
|
|
272
|
+
virtual void writeImpl(const MessageData &) = 0;
|
|
273
|
+
|
|
274
|
+
/// Implementation for tryWrite(). Subclasses must implement this.
|
|
275
|
+
virtual bool tryWriteImpl(const MessageData &data) = 0;
|
|
276
|
+
|
|
277
|
+
/// Whether to translate outgoing data if the port type is a window type. Set
|
|
278
|
+
/// by the connect() method.
|
|
279
|
+
bool translateMessages = false;
|
|
280
|
+
/// If tryWrite cannot write all the messages of a windowed type at once, it
|
|
281
|
+
/// stores them here and writes them out one by one on subsequent calls.
|
|
282
|
+
std::vector<MessageData> translationBuffer;
|
|
283
|
+
/// Index of the next message to write in translationBuffer.
|
|
284
|
+
size_t translationBufferIdx = 0;
|
|
285
|
+
/// Translate outgoing data if the port type is a window type. Append the new
|
|
286
|
+
/// message 'chunks' to translationBuffer.
|
|
287
|
+
void translateOutgoing(const MessageData &data);
|
|
97
288
|
|
|
98
289
|
private:
|
|
99
290
|
volatile bool connected = false;
|
|
@@ -105,15 +296,18 @@ public:
|
|
|
105
296
|
UnknownWriteChannelPort(const Type *type, std::string errmsg)
|
|
106
297
|
: WriteChannelPort(type), errmsg(errmsg) {}
|
|
107
298
|
|
|
108
|
-
void connect(
|
|
299
|
+
void connect(const ConnectOptions &options = {}) override {
|
|
109
300
|
throw std::runtime_error(errmsg);
|
|
110
301
|
}
|
|
111
|
-
|
|
112
|
-
|
|
302
|
+
|
|
303
|
+
protected:
|
|
304
|
+
void writeImpl(const MessageData &) override {
|
|
305
|
+
throw std::runtime_error(errmsg);
|
|
306
|
+
}
|
|
307
|
+
bool tryWriteImpl(const MessageData &) override {
|
|
113
308
|
throw std::runtime_error(errmsg);
|
|
114
309
|
}
|
|
115
310
|
|
|
116
|
-
protected:
|
|
117
311
|
std::string errmsg;
|
|
118
312
|
};
|
|
119
313
|
|
|
@@ -143,7 +337,7 @@ public:
|
|
|
143
337
|
//===--------------------------------------------------------------------===//
|
|
144
338
|
|
|
145
339
|
virtual void connect(std::function<bool(MessageData)> callback,
|
|
146
|
-
|
|
340
|
+
const ConnectOptions &options = {});
|
|
147
341
|
|
|
148
342
|
//===--------------------------------------------------------------------===//
|
|
149
343
|
// Polling mode methods: To use futures or blocking reads, connect without any
|
|
@@ -154,8 +348,7 @@ public:
|
|
|
154
348
|
static constexpr uint64_t DefaultMaxDataQueueMsgs = 32;
|
|
155
349
|
|
|
156
350
|
/// Connect to the channel in polling mode.
|
|
157
|
-
virtual void
|
|
158
|
-
connect(std::optional<unsigned> bufferSize = std::nullopt) override;
|
|
351
|
+
virtual void connect(const ConnectOptions &options = {}) override;
|
|
159
352
|
|
|
160
353
|
/// Asynchronous read.
|
|
161
354
|
virtual std::future<MessageData> readAsync();
|
|
@@ -184,6 +377,20 @@ protected:
|
|
|
184
377
|
/// Backends call this callback when new data is available.
|
|
185
378
|
std::function<bool(MessageData)> callback;
|
|
186
379
|
|
|
380
|
+
/// Window translation support.
|
|
381
|
+
std::vector<uint8_t> translationBuffer;
|
|
382
|
+
/// Index of the next expected frame (for multi-frame windows).
|
|
383
|
+
size_t nextFrameIndex = 0;
|
|
384
|
+
/// For list fields: accumulated list data across frames.
|
|
385
|
+
std::vector<uint8_t> listDataBuffer;
|
|
386
|
+
/// Flag to track whether we're in the middle of accumulating list data.
|
|
387
|
+
bool accumulatingListData = false;
|
|
388
|
+
/// Reset translation state buffers and indices.
|
|
389
|
+
void resetTranslationState();
|
|
390
|
+
/// Translate incoming data if the port type is a window type. Returns true if
|
|
391
|
+
/// the message has been completely received.
|
|
392
|
+
bool translateIncoming(MessageData &data);
|
|
393
|
+
|
|
187
394
|
//===--------------------------------------------------------------------===//
|
|
188
395
|
// Polling mode members.
|
|
189
396
|
//===--------------------------------------------------------------------===//
|
|
@@ -206,10 +413,10 @@ public:
|
|
|
206
413
|
: ReadChannelPort(type), errmsg(errmsg) {}
|
|
207
414
|
|
|
208
415
|
void connect(std::function<bool(MessageData)> callback,
|
|
209
|
-
|
|
416
|
+
const ConnectOptions &options = ConnectOptions()) override {
|
|
210
417
|
throw std::runtime_error(errmsg);
|
|
211
418
|
}
|
|
212
|
-
void connect(
|
|
419
|
+
void connect(const ConnectOptions &options = ConnectOptions()) override {
|
|
213
420
|
throw std::runtime_error(errmsg);
|
|
214
421
|
}
|
|
215
422
|
std::future<MessageData> readAsync() override {
|
esiaccel/include/esi/Services.h
CHANGED
|
@@ -25,10 +25,21 @@
|
|
|
25
25
|
#include "esi/Ports.h"
|
|
26
26
|
|
|
27
27
|
#include <cstdint>
|
|
28
|
+
#include <list>
|
|
28
29
|
|
|
29
30
|
namespace esi {
|
|
30
31
|
class AcceleratorConnection;
|
|
31
32
|
class Engine;
|
|
33
|
+
namespace services {
|
|
34
|
+
class Service;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// While building the design, keep around a std::map of active services indexed
|
|
38
|
+
// by the service name. When a new service is encountered during descent, add it
|
|
39
|
+
// to the table (perhaps overwriting one). Modifications to the table only apply
|
|
40
|
+
// to the current branch, so copy this and update it at each level of the tree.
|
|
41
|
+
using ServiceTable = std::map<std::string, services::Service *>;
|
|
42
|
+
|
|
32
43
|
namespace services {
|
|
33
44
|
|
|
34
45
|
/// Add a custom interface to a service client at a particular point in the
|
|
@@ -38,7 +49,9 @@ public:
|
|
|
38
49
|
using BundlePort::BundlePort;
|
|
39
50
|
virtual ~ServicePort() = default;
|
|
40
51
|
// Get a description of the service port.
|
|
41
|
-
virtual std::optional<std::string> toString() const {
|
|
52
|
+
virtual std::optional<std::string> toString(bool oneLine = false) const {
|
|
53
|
+
return std::nullopt;
|
|
54
|
+
}
|
|
42
55
|
};
|
|
43
56
|
|
|
44
57
|
/// Parent class of all APIs modeled as 'services'. May or may not map to a
|
|
@@ -107,6 +120,14 @@ public:
|
|
|
107
120
|
/// Get the ESI version number to check version compatibility.
|
|
108
121
|
virtual uint32_t getEsiVersion() const = 0;
|
|
109
122
|
|
|
123
|
+
/// Get the current cycle count of the accelerator system.
|
|
124
|
+
virtual std::optional<uint64_t> getCycleCount() const { return std::nullopt; }
|
|
125
|
+
/// Get the "core" clock frequency of the accelerator system in Hz. Returns
|
|
126
|
+
/// nullopt if the accelerator does not provide this information.
|
|
127
|
+
virtual std::optional<uint64_t> getCoreClockFrequency() const {
|
|
128
|
+
return std::nullopt;
|
|
129
|
+
}
|
|
130
|
+
|
|
110
131
|
/// Return the JSON-formatted system manifest.
|
|
111
132
|
virtual std::string getJsonManifest() const;
|
|
112
133
|
|
|
@@ -170,7 +191,8 @@ public:
|
|
|
170
191
|
/// Write a 64-bit value to this region, not the global address space.
|
|
171
192
|
virtual void write(uint32_t addr, uint64_t data);
|
|
172
193
|
|
|
173
|
-
virtual std::optional<std::string>
|
|
194
|
+
virtual std::optional<std::string>
|
|
195
|
+
toString(bool oneLine = false) const override {
|
|
174
196
|
return "MMIO region " + toHex(desc.base) + " - " +
|
|
175
197
|
toHex(desc.base + desc.size);
|
|
176
198
|
}
|
|
@@ -189,6 +211,12 @@ public:
|
|
|
189
211
|
/// Get the ESI version number to check version compatibility.
|
|
190
212
|
uint32_t getEsiVersion() const override;
|
|
191
213
|
|
|
214
|
+
/// Get the current cycle count of the accelerator system's core clock.
|
|
215
|
+
std::optional<uint64_t> getCycleCount() const override;
|
|
216
|
+
/// Get the "core" clock frequency of the accelerator system in Hz. Returns
|
|
217
|
+
/// nullopt if the accelerator does not provide this information.
|
|
218
|
+
std::optional<uint64_t> getCoreClockFrequency() const override;
|
|
219
|
+
|
|
192
220
|
/// Return the zlib compressed JSON system manifest.
|
|
193
221
|
virtual std::vector<uint8_t> getCompressedManifest() const override;
|
|
194
222
|
|
|
@@ -282,10 +310,12 @@ public:
|
|
|
282
310
|
->getInner();
|
|
283
311
|
}
|
|
284
312
|
|
|
285
|
-
virtual std::optional<std::string>
|
|
313
|
+
virtual std::optional<std::string>
|
|
314
|
+
toString(bool oneLine = false) const override {
|
|
286
315
|
const esi::Type *argType = getArgType();
|
|
287
316
|
const esi::Type *resultType = getResultType();
|
|
288
|
-
return "function " + resultType->
|
|
317
|
+
return "function " + resultType->toString(oneLine) + "(" +
|
|
318
|
+
argType->toString(oneLine) + ")";
|
|
289
319
|
}
|
|
290
320
|
|
|
291
321
|
private:
|
|
@@ -338,10 +368,12 @@ public:
|
|
|
338
368
|
->getInner();
|
|
339
369
|
}
|
|
340
370
|
|
|
341
|
-
virtual std::optional<std::string>
|
|
371
|
+
virtual std::optional<std::string>
|
|
372
|
+
toString(bool oneLine = false) const override {
|
|
342
373
|
const esi::Type *argType = getArgType();
|
|
343
374
|
const esi::Type *resultType = getResultType();
|
|
344
|
-
return "callback " + resultType->
|
|
375
|
+
return "callback " + resultType->toString(oneLine) + "(" +
|
|
376
|
+
argType->toString(oneLine) + ")";
|
|
345
377
|
}
|
|
346
378
|
|
|
347
379
|
private:
|
|
@@ -365,37 +397,51 @@ public:
|
|
|
365
397
|
virtual std::string getServiceSymbol() const override;
|
|
366
398
|
virtual BundlePort *getPort(AppIDPath id,
|
|
367
399
|
const BundleType *type) const override;
|
|
400
|
+
virtual Service *getChildService(Service::Type service, AppIDPath id = {},
|
|
401
|
+
std::string implName = {},
|
|
402
|
+
ServiceImplDetails details = {},
|
|
403
|
+
HWClientDetails clients = {}) override;
|
|
404
|
+
MMIO::MMIORegion *getMMIORegion() const;
|
|
368
405
|
|
|
369
406
|
/// A telemetry port which gets attached to a service port.
|
|
370
|
-
class
|
|
407
|
+
class Metric : public ServicePort {
|
|
371
408
|
friend class TelemetryService;
|
|
372
|
-
|
|
409
|
+
Metric(AppID id, const BundleType *type, PortMap channels,
|
|
410
|
+
const TelemetryService *telemetryService,
|
|
411
|
+
std::optional<uint64_t> offset);
|
|
373
412
|
|
|
374
413
|
public:
|
|
375
|
-
static Telemetry *get(AppID id, BundleType *type, WriteChannelPort &get,
|
|
376
|
-
ReadChannelPort &data);
|
|
377
|
-
|
|
378
414
|
void connect();
|
|
379
415
|
std::future<MessageData> read();
|
|
416
|
+
uint64_t readInt();
|
|
380
417
|
|
|
381
|
-
virtual std::optional<std::string>
|
|
418
|
+
virtual std::optional<std::string>
|
|
419
|
+
toString(bool oneLine = false) const override {
|
|
382
420
|
const esi::Type *dataType =
|
|
383
421
|
dynamic_cast<const ChannelType *>(type->findChannel("data").first)
|
|
384
422
|
->getInner();
|
|
385
|
-
return "telemetry " + dataType->
|
|
423
|
+
return "telemetry " + dataType->toString(oneLine);
|
|
386
424
|
}
|
|
387
425
|
|
|
388
426
|
private:
|
|
389
|
-
|
|
390
|
-
|
|
427
|
+
const TelemetryService *telemetryService;
|
|
428
|
+
MMIO::MMIORegion *mmio;
|
|
429
|
+
std::optional<uint64_t> offset;
|
|
391
430
|
};
|
|
392
431
|
|
|
393
|
-
|
|
394
|
-
|
|
432
|
+
std::map<AppIDPath, Metric *> getTelemetryPorts() {
|
|
433
|
+
std::map<AppIDPath, Metric *> ports;
|
|
434
|
+
getTelemetryPorts(ports);
|
|
435
|
+
return ports;
|
|
395
436
|
}
|
|
437
|
+
void getTelemetryPorts(std::map<AppIDPath, Metric *> &ports);
|
|
396
438
|
|
|
397
439
|
private:
|
|
398
|
-
|
|
440
|
+
AppIDPath id;
|
|
441
|
+
mutable MMIO::MMIORegion *mmio;
|
|
442
|
+
std::map<AppIDPath, uint64_t> portAddressAssignments;
|
|
443
|
+
mutable std::map<AppIDPath, Metric *> telemetryPorts;
|
|
444
|
+
std::list<TelemetryService *> children;
|
|
399
445
|
};
|
|
400
446
|
|
|
401
447
|
/// Registry of services which can be instantiated directly by the Accelerator
|
esiaccel/include/esi/Types.h
CHANGED
|
@@ -80,6 +80,12 @@ public:
|
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
// Dump a textual representation of this type to the provided stream.
|
|
84
|
+
void dump(std::ostream &os, bool oneLine = false) const;
|
|
85
|
+
|
|
86
|
+
// Return a textual representation of this type.
|
|
87
|
+
std::string toString(bool oneLine = false) const;
|
|
88
|
+
|
|
83
89
|
protected:
|
|
84
90
|
ID id;
|
|
85
91
|
};
|
|
@@ -268,6 +274,61 @@ private:
|
|
|
268
274
|
bool reverse;
|
|
269
275
|
};
|
|
270
276
|
|
|
277
|
+
/// Windows represent a fixed-size sliding window over a stream of data.
|
|
278
|
+
/// They define an "into" type (the data structure being windowed) and a
|
|
279
|
+
/// "loweredType" (the hardware representation including control signals).
|
|
280
|
+
class WindowType : public Type {
|
|
281
|
+
public:
|
|
282
|
+
/// Field information describing a field within a frame.
|
|
283
|
+
struct Field {
|
|
284
|
+
std::string name;
|
|
285
|
+
uint64_t numItems = 0; // 0 means not specified (use all items)
|
|
286
|
+
uint64_t bulkCountWidth = 0; // 0 means parallel encoding, >0 means serial
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
/// Frame information describing which fields are included in a particular
|
|
290
|
+
/// frame.
|
|
291
|
+
struct Frame {
|
|
292
|
+
std::string name;
|
|
293
|
+
std::vector<Field> fields;
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
WindowType(const ID &id, const std::string &name, const Type *intoType,
|
|
297
|
+
const Type *loweredType, const std::vector<Frame> &frames)
|
|
298
|
+
: Type(id), name(name), intoType(intoType), loweredType(loweredType),
|
|
299
|
+
frames(frames) {}
|
|
300
|
+
|
|
301
|
+
const std::string &getName() const { return name; }
|
|
302
|
+
const Type *getIntoType() const { return intoType; }
|
|
303
|
+
const Type *getLoweredType() const { return loweredType; }
|
|
304
|
+
const std::vector<Frame> &getFrames() const { return frames; }
|
|
305
|
+
|
|
306
|
+
std::ptrdiff_t getBitWidth() const override {
|
|
307
|
+
return loweredType->getBitWidth();
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
private:
|
|
311
|
+
std::string name;
|
|
312
|
+
const Type *intoType;
|
|
313
|
+
const Type *loweredType;
|
|
314
|
+
std::vector<Frame> frames;
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
/// Lists represent variable-length sequences of elements of a single type.
|
|
318
|
+
/// Unlike arrays which have a fixed size, lists can have any length.
|
|
319
|
+
class ListType : public Type {
|
|
320
|
+
public:
|
|
321
|
+
ListType(const ID &id, const Type *elementType)
|
|
322
|
+
: Type(id), elementType(elementType) {}
|
|
323
|
+
|
|
324
|
+
const Type *getElementType() const { return elementType; }
|
|
325
|
+
|
|
326
|
+
std::ptrdiff_t getBitWidth() const override { return -1; }
|
|
327
|
+
|
|
328
|
+
private:
|
|
329
|
+
const Type *elementType;
|
|
330
|
+
};
|
|
331
|
+
|
|
271
332
|
} // namespace esi
|
|
272
333
|
|
|
273
334
|
#endif // ESI_TYPES_H
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
//===----------------------------------------------------------------------===//
|
|
8
8
|
//
|
|
9
9
|
// This is a specialization of the ESI C++ API (backend) for connection into a
|
|
10
|
-
// simulation of an ESI system. Currently uses
|
|
11
|
-
//
|
|
10
|
+
// simulation of an ESI system. Currently uses gRPC, but that could change.
|
|
11
|
+
// Requires gRPC C++ library.
|
|
12
12
|
//
|
|
13
13
|
// DO NOT EDIT!
|
|
14
14
|
// This file is distributed as part of an ESI package. The source for this file
|
|
@@ -26,13 +26,11 @@
|
|
|
26
26
|
#include <set>
|
|
27
27
|
|
|
28
28
|
namespace esi {
|
|
29
|
-
namespace cosim {
|
|
30
|
-
class ChannelDesc;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
29
|
namespace backends {
|
|
34
30
|
namespace cosim {
|
|
31
|
+
|
|
35
32
|
class CosimEngine;
|
|
33
|
+
class RpcClient;
|
|
36
34
|
|
|
37
35
|
/// Connect to an ESI simulation.
|
|
38
36
|
class CosimAccelerator : public esi::AcceleratorConnection {
|
|
@@ -53,11 +51,6 @@ public:
|
|
|
53
51
|
// Set the way this connection will retrieve the manifest.
|
|
54
52
|
void setManifestMethod(ManifestMethod method);
|
|
55
53
|
|
|
56
|
-
// C++ doesn't have a mechanism to forward declare a nested class and we don't
|
|
57
|
-
// want to include the generated header here. So we have to wrap it in a
|
|
58
|
-
// forward-declared struct we write ourselves.
|
|
59
|
-
struct StubContainer;
|
|
60
|
-
|
|
61
54
|
void createEngine(const std::string &engineTypeName, AppIDPath idPath,
|
|
62
55
|
const ServiceImplDetails &details,
|
|
63
56
|
const HWClientDetails &clients) override;
|
|
@@ -69,7 +62,7 @@ protected:
|
|
|
69
62
|
const HWClientDetails &clients) override;
|
|
70
63
|
|
|
71
64
|
private:
|
|
72
|
-
|
|
65
|
+
std::unique_ptr<RpcClient> rpcClient;
|
|
73
66
|
|
|
74
67
|
// We own all channels connected to rpcClient since their lifetime is tied to
|
|
75
68
|
// rpcClient.
|