esiaccel 0.2.2__cp312-cp312-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.

Potentially problematic release.


This version of esiaccel might be problematic. Click here for more details.

Files changed (57) hide show
  1. esiaccel/CosimBackend.dll +0 -0
  2. esiaccel/CosimBackend.lib +0 -0
  3. esiaccel/CosimRpc.dll +0 -0
  4. esiaccel/CosimRpc.lib +0 -0
  5. esiaccel/ESICppRuntime.dll +0 -0
  6. esiaccel/ESICppRuntime.lib +0 -0
  7. esiaccel/EsiCosimDpiServer.dll +0 -0
  8. esiaccel/EsiCosimDpiServer.lib +0 -0
  9. esiaccel/MtiPli.dll +0 -0
  10. esiaccel/MtiPli.lib +0 -0
  11. esiaccel/__init__.py +31 -0
  12. esiaccel/abseil_dll.dll +0 -0
  13. esiaccel/accelerator.py +134 -0
  14. esiaccel/cares.dll +0 -0
  15. esiaccel/cmake/esiaccelConfig.cmake +49 -0
  16. esiaccel/codegen.py +197 -0
  17. esiaccel/cosim/Cosim_DpiPkg.sv +85 -0
  18. esiaccel/cosim/Cosim_Endpoint.sv +218 -0
  19. esiaccel/cosim/Cosim_Manifest.sv +32 -0
  20. esiaccel/cosim/driver.cpp +131 -0
  21. esiaccel/cosim/driver.sv +74 -0
  22. esiaccel/cosim/questa.py +141 -0
  23. esiaccel/cosim/simulator.py +382 -0
  24. esiaccel/cosim/verilator.py +92 -0
  25. esiaccel/esi-cosim.py +104 -0
  26. esiaccel/esiCppAccel.cp312-win_amd64.pyd +0 -0
  27. esiaccel/esiquery.exe +0 -0
  28. esiaccel/include/esi/Accelerator.h +219 -0
  29. esiaccel/include/esi/CLI.h +77 -0
  30. esiaccel/include/esi/Common.h +182 -0
  31. esiaccel/include/esi/Context.h +82 -0
  32. esiaccel/include/esi/Design.h +132 -0
  33. esiaccel/include/esi/Engines.h +124 -0
  34. esiaccel/include/esi/Logging.h +231 -0
  35. esiaccel/include/esi/Manifest.h +70 -0
  36. esiaccel/include/esi/Ports.h +482 -0
  37. esiaccel/include/esi/Services.h +453 -0
  38. esiaccel/include/esi/Types.h +334 -0
  39. esiaccel/include/esi/Utils.h +102 -0
  40. esiaccel/include/esi/Values.h +313 -0
  41. esiaccel/include/esi/backends/Cosim.h +78 -0
  42. esiaccel/include/esi/backends/RpcClient.h +97 -0
  43. esiaccel/include/esi/backends/RpcServer.h +73 -0
  44. esiaccel/include/esi/backends/Trace.h +87 -0
  45. esiaccel/libcrypto-3-x64.dll +0 -0
  46. esiaccel/libprotobuf.dll +0 -0
  47. esiaccel/libssl-3-x64.dll +0 -0
  48. esiaccel/re2.dll +0 -0
  49. esiaccel/types.py +565 -0
  50. esiaccel/utils.py +54 -0
  51. esiaccel/zlib1.dll +0 -0
  52. esiaccel-0.2.2.dist-info/METADATA +254 -0
  53. esiaccel-0.2.2.dist-info/RECORD +57 -0
  54. esiaccel-0.2.2.dist-info/WHEEL +5 -0
  55. esiaccel-0.2.2.dist-info/entry_points.txt +4 -0
  56. esiaccel-0.2.2.dist-info/licenses/LICENSE +234 -0
  57. esiaccel-0.2.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,482 @@
1
+ //===- Ports.h - ESI communication channels ---------------------*- C++ -*-===//
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
+ // DO NOT EDIT!
10
+ // This file is distributed as part of an ESI package. The source for this file
11
+ // should always be modified within CIRCT.
12
+ //
13
+ //===----------------------------------------------------------------------===//
14
+
15
+ // NOLINTNEXTLINE(llvm-header-guard)
16
+ #ifndef ESI_PORTS_H
17
+ #define ESI_PORTS_H
18
+
19
+ #include "esi/Common.h"
20
+ #include "esi/Types.h"
21
+ #include "esi/Utils.h"
22
+
23
+ #include <cassert>
24
+ #include <future>
25
+
26
+ namespace esi {
27
+
28
+ class ChannelPort;
29
+ using PortMap = std::map<std::string, ChannelPort &>;
30
+
31
+ /// Unidirectional channels are the basic communication primitive between the
32
+ /// host and accelerator. A 'ChannelPort' is the host side of a channel. It can
33
+ /// be either read or write but not both. At this level, channels are untyped --
34
+ /// just streams of bytes. They are not intended to be used directly by users
35
+ /// but used by higher level APIs which add types.
36
+ class ChannelPort {
37
+ public:
38
+ ChannelPort(const Type *type);
39
+ virtual ~ChannelPort() {}
40
+
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;
113
+ virtual void disconnect() = 0;
114
+ virtual bool isConnected() const = 0;
115
+
116
+ /// Poll for incoming data. Returns true if data was read or written into a
117
+ /// buffer as a result of the poll. Calling the call back could (will) also
118
+ /// happen in that case. Some backends need this to be called periodically. In
119
+ /// the usual case, this will be called by a background thread, but the ESI
120
+ /// runtime does not want to assume that the host processes use standard
121
+ /// threads. If the user wants to provide their own threads, they need to call
122
+ /// this on each port occasionally. This is also called from the 'master' poll
123
+ /// method in the Accelerator class.
124
+ bool poll() {
125
+ if (isConnected())
126
+ return pollImpl();
127
+ return false;
128
+ }
129
+
130
+ const Type *getType() const { return type; }
131
+
132
+ protected:
133
+ const Type *type;
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
+
196
+ /// Method called by poll() to actually poll the channel if the channel is
197
+ /// connected.
198
+ virtual bool pollImpl() { return false; }
199
+
200
+ /// Called by all connect methods to let backends initiate the underlying
201
+ /// connections.
202
+ virtual void connectImpl(const ConnectOptions &options) {}
203
+ };
204
+
205
+ /// A ChannelPort which sends data to the accelerator.
206
+ class WriteChannelPort : public ChannelPort {
207
+ public:
208
+ using ChannelPort::ChannelPort;
209
+
210
+ virtual void connect(const ConnectOptions &options = {}) override {
211
+ translateMessages = options.translateMessage && translationInfo;
212
+ if (translateMessages)
213
+ translationInfo->precomputeFrameInfo();
214
+ connectImpl(options);
215
+ connected = true;
216
+ }
217
+ virtual void disconnect() override { connected = false; }
218
+ virtual bool isConnected() const override { return connected; }
219
+
220
+ /// A very basic blocking write API. Will likely change for performance
221
+ /// reasons.
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
+ }
269
+
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);
288
+
289
+ private:
290
+ volatile bool connected = false;
291
+ };
292
+
293
+ /// Instantiated when a backend does not know how to create a write channel.
294
+ class UnknownWriteChannelPort : public WriteChannelPort {
295
+ public:
296
+ UnknownWriteChannelPort(const Type *type, std::string errmsg)
297
+ : WriteChannelPort(type), errmsg(errmsg) {}
298
+
299
+ void connect(const ConnectOptions &options = {}) override {
300
+ throw std::runtime_error(errmsg);
301
+ }
302
+
303
+ protected:
304
+ void writeImpl(const MessageData &) override {
305
+ throw std::runtime_error(errmsg);
306
+ }
307
+ bool tryWriteImpl(const MessageData &) override {
308
+ throw std::runtime_error(errmsg);
309
+ }
310
+
311
+ std::string errmsg;
312
+ };
313
+
314
+ /// A ChannelPort which reads data from the accelerator. It has two modes:
315
+ /// Callback and Polling which cannot be used at the same time. The mode is set
316
+ /// at connect() time. To change the mode, disconnect() and then connect()
317
+ /// again.
318
+ class ReadChannelPort : public ChannelPort {
319
+
320
+ public:
321
+ ReadChannelPort(const Type *type)
322
+ : ChannelPort(type), mode(Mode::Disconnected) {}
323
+ virtual void disconnect() override { mode = Mode::Disconnected; }
324
+ virtual bool isConnected() const override {
325
+ return mode != Mode::Disconnected;
326
+ }
327
+
328
+ //===--------------------------------------------------------------------===//
329
+ // Callback mode: To use a callback, connect with a callback function which
330
+ // will get called with incoming data. This function can be called from any
331
+ // thread. It shall return true to indicate that the data was consumed. False
332
+ // if it could not accept the data and should be tried again at some point in
333
+ // the future. Callback is not allowed to block and needs to execute quickly.
334
+ //
335
+ // TODO: Have the callback return something upon which the caller can check,
336
+ // wait, and be notified.
337
+ //===--------------------------------------------------------------------===//
338
+
339
+ virtual void connect(std::function<bool(MessageData)> callback,
340
+ const ConnectOptions &options = {});
341
+
342
+ //===--------------------------------------------------------------------===//
343
+ // Polling mode methods: To use futures or blocking reads, connect without any
344
+ // arguments. You will then be able to use readAsync() or read().
345
+ //===--------------------------------------------------------------------===//
346
+
347
+ /// Default max data queue size set at connect time.
348
+ static constexpr uint64_t DefaultMaxDataQueueMsgs = 32;
349
+
350
+ /// Connect to the channel in polling mode.
351
+ virtual void connect(const ConnectOptions &options = {}) override;
352
+
353
+ /// Asynchronous read.
354
+ virtual std::future<MessageData> readAsync();
355
+
356
+ /// Specify a buffer to read into. Blocking. Basic API, will likely change
357
+ /// for performance and functionality reasons.
358
+ virtual void read(MessageData &outData) {
359
+ std::future<MessageData> f = readAsync();
360
+ f.wait();
361
+ outData = std::move(f.get());
362
+ }
363
+
364
+ /// Set maximum number of messages to store in the dataQueue. 0 means no
365
+ /// limit. This is only used in polling mode and is set to default of 32 upon
366
+ /// connect. While it may seem redundant to have this and bufferSize, there
367
+ /// may be (and are) backends which have a very small amount of memory which
368
+ /// are accelerator accessible and want to move messages out as quickly as
369
+ /// possible.
370
+ void setMaxDataQueueMsgs(uint64_t maxMsgs) { maxDataQueueMsgs = maxMsgs; }
371
+
372
+ protected:
373
+ /// Indicates the current mode of the channel.
374
+ enum Mode { Disconnected, Callback, Polling };
375
+ volatile Mode mode;
376
+
377
+ /// Backends call this callback when new data is available.
378
+ std::function<bool(MessageData)> callback;
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
+
394
+ //===--------------------------------------------------------------------===//
395
+ // Polling mode members.
396
+ //===--------------------------------------------------------------------===//
397
+
398
+ /// Mutex to protect the two queues used for polling.
399
+ std::mutex pollingM;
400
+ /// Store incoming data here if there are no outstanding promises to be
401
+ /// fulfilled.
402
+ std::queue<MessageData> dataQueue;
403
+ /// Maximum number of messages to store in dataQueue. 0 means no limit.
404
+ uint64_t maxDataQueueMsgs;
405
+ /// Promises to be fulfilled when data is available.
406
+ std::queue<std::promise<MessageData>> promiseQueue;
407
+ };
408
+
409
+ /// Instantiated when a backend does not know how to create a read channel.
410
+ class UnknownReadChannelPort : public ReadChannelPort {
411
+ public:
412
+ UnknownReadChannelPort(const Type *type, std::string errmsg)
413
+ : ReadChannelPort(type), errmsg(errmsg) {}
414
+
415
+ void connect(std::function<bool(MessageData)> callback,
416
+ const ConnectOptions &options = ConnectOptions()) override {
417
+ throw std::runtime_error(errmsg);
418
+ }
419
+ void connect(const ConnectOptions &options = ConnectOptions()) override {
420
+ throw std::runtime_error(errmsg);
421
+ }
422
+ std::future<MessageData> readAsync() override {
423
+ throw std::runtime_error(errmsg);
424
+ }
425
+
426
+ protected:
427
+ std::string errmsg;
428
+ };
429
+
430
+ /// Services provide connections to 'bundles' -- collections of named,
431
+ /// unidirectional communication channels. This class provides access to those
432
+ /// ChannelPorts.
433
+ class BundlePort {
434
+ public:
435
+ /// Compute the direction of a channel given the bundle direction and the
436
+ /// bundle port's direction.
437
+ static bool isWrite(BundleType::Direction bundleDir) {
438
+ return bundleDir == BundleType::Direction::To;
439
+ }
440
+
441
+ /// Construct a port.
442
+ BundlePort(AppID id, const BundleType *type, PortMap channels);
443
+ virtual ~BundlePort() = default;
444
+
445
+ /// Get the ID of the port.
446
+ AppID getID() const { return id; }
447
+
448
+ /// Get access to the raw byte streams of a channel. Intended for internal
449
+ /// usage and binding to other languages (e.g. Python) which have their own
450
+ /// message serialization code. Exposed publicly as an escape hatch, but
451
+ /// ordinary users should not use. You have been warned.
452
+ WriteChannelPort &getRawWrite(const std::string &name) const;
453
+ ReadChannelPort &getRawRead(const std::string &name) const;
454
+ const PortMap &getChannels() const { return channels; }
455
+
456
+ /// Cast this Bundle port to a subclass which is actually useful. Returns
457
+ /// nullptr if the cast fails.
458
+ // TODO: this probably shouldn't be 'const', but bundle ports' user access are
459
+ // const. Change that.
460
+ template <typename T>
461
+ T *getAs() const {
462
+ return const_cast<T *>(dynamic_cast<const T *>(this));
463
+ }
464
+
465
+ /// Calls `poll` on all channels in the bundle and returns true if any of them
466
+ /// returned true.
467
+ bool poll() {
468
+ bool result = false;
469
+ for (auto &channel : channels)
470
+ result |= channel.second.poll();
471
+ return result;
472
+ }
473
+
474
+ protected:
475
+ AppID id;
476
+ const BundleType *type;
477
+ PortMap channels;
478
+ };
479
+
480
+ } // namespace esi
481
+
482
+ #endif // ESI_PORTS_H