esiaccel 0.1.5.dev315__cp311-cp311-win_amd64.whl → 0.2.3.dev47__cp311-cp311-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.
Files changed (45) 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 +12 -3
  12. esiaccel/abseil_dll.dll +0 -0
  13. esiaccel/accelerator.py +37 -5
  14. esiaccel/cares.dll +0 -0
  15. esiaccel/cmake/esiaccelConfig.cmake +34 -0
  16. esiaccel/codegen.py +3 -3
  17. esiaccel/esiCppAccel.cp312-win_amd64.pyd +0 -0
  18. esiaccel/esiquery.exe +0 -0
  19. esiaccel/include/esi/Accelerator.h +3 -16
  20. esiaccel/include/esi/CLI.h +5 -5
  21. esiaccel/include/esi/Common.h +11 -1
  22. esiaccel/include/esi/Context.h +17 -9
  23. esiaccel/include/esi/Design.h +9 -4
  24. esiaccel/include/esi/Manifest.h +0 -2
  25. esiaccel/include/esi/Ports.h +230 -23
  26. esiaccel/include/esi/Services.h +50 -18
  27. esiaccel/include/esi/Types.h +100 -29
  28. esiaccel/include/esi/Values.h +313 -0
  29. esiaccel/include/esi/backends/Cosim.h +5 -12
  30. esiaccel/include/esi/backends/RpcClient.h +97 -0
  31. esiaccel/include/esi/backends/RpcServer.h +21 -3
  32. esiaccel/libcrypto-3-x64.dll +0 -0
  33. esiaccel/libprotobuf.dll +0 -0
  34. esiaccel/libssl-3-x64.dll +0 -0
  35. esiaccel/re2.dll +0 -0
  36. esiaccel/types.py +6 -4
  37. esiaccel/zlib1.dll +0 -0
  38. {esiaccel-0.1.5.dev315.dist-info → esiaccel-0.2.3.dev47.dist-info}/METADATA +1 -1
  39. esiaccel-0.2.3.dev47.dist-info/RECORD +57 -0
  40. esiaccel/esiCppAccel.cp311-win_amd64.pyd +0 -0
  41. esiaccel-0.1.5.dev315.dist-info/RECORD +0 -53
  42. {esiaccel-0.1.5.dev315.dist-info → esiaccel-0.2.3.dev47.dist-info}/WHEEL +0 -0
  43. {esiaccel-0.1.5.dev315.dist-info → esiaccel-0.2.3.dev47.dist-info}/entry_points.txt +0 -0
  44. {esiaccel-0.1.5.dev315.dist-info → esiaccel-0.2.3.dev47.dist-info}/licenses/LICENSE +0 -0
  45. {esiaccel-0.1.5.dev315.dist-info → esiaccel-0.2.3.dev47.dist-info}/top_level.txt +0 -0
@@ -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) : type(type) {}
38
+ ChannelPort(const Type *type);
39
39
  virtual ~ChannelPort() {}
40
40
 
41
- /// Set up a connection to the accelerator. The buffer size is optional and
42
- /// should be considered merely a hint. Individual implementations use it
43
- /// however they like. The unit is number of messages of the port type.
44
- virtual void connect(std::optional<unsigned> bufferSize = std::nullopt) = 0;
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(std::optional<unsigned> bufferSize) {}
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
- connect(std::optional<unsigned> bufferSize = std::nullopt) override {
83
- connectImpl(bufferSize);
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
- virtual void write(const MessageData &) = 0;
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
- /// A basic non-blocking write API. Returns true if the data was written.
94
- /// It is invalid for backends to always return false (i.e. backends must
95
- /// eventually ensure that writes may succeed).
96
- virtual bool tryWrite(const MessageData &data) = 0;
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(std::optional<unsigned> bufferSize = std::nullopt) override {
299
+ void connect(const ConnectOptions &options = {}) override {
109
300
  throw std::runtime_error(errmsg);
110
301
  }
111
- void write(const MessageData &) override { throw std::runtime_error(errmsg); }
112
- bool tryWrite(const MessageData &) override {
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
- std::optional<unsigned> bufferSize = std::nullopt);
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
- std::optional<unsigned> bufferSize = std::nullopt) override {
416
+ const ConnectOptions &options = ConnectOptions()) override {
210
417
  throw std::runtime_error(errmsg);
211
418
  }
212
- void connect(std::optional<unsigned> bufferSize = std::nullopt) override {
419
+ void connect(const ConnectOptions &options = ConnectOptions()) override {
213
420
  throw std::runtime_error(errmsg);
214
421
  }
215
422
  std::future<MessageData> readAsync() override {
@@ -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 { return std::nullopt; }
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
@@ -170,7 +183,8 @@ public:
170
183
  /// Write a 64-bit value to this region, not the global address space.
171
184
  virtual void write(uint32_t addr, uint64_t data);
172
185
 
173
- virtual std::optional<std::string> toString() const override {
186
+ virtual std::optional<std::string>
187
+ toString(bool oneLine = false) const override {
174
188
  return "MMIO region " + toHex(desc.base) + " - " +
175
189
  toHex(desc.base + desc.size);
176
190
  }
@@ -282,10 +296,12 @@ public:
282
296
  ->getInner();
283
297
  }
284
298
 
285
- virtual std::optional<std::string> toString() const override {
299
+ virtual std::optional<std::string>
300
+ toString(bool oneLine = false) const override {
286
301
  const esi::Type *argType = getArgType();
287
302
  const esi::Type *resultType = getResultType();
288
- return "function " + resultType->getID() + "(" + argType->getID() + ")";
303
+ return "function " + resultType->toString(oneLine) + "(" +
304
+ argType->toString(oneLine) + ")";
289
305
  }
290
306
 
291
307
  private:
@@ -338,10 +354,12 @@ public:
338
354
  ->getInner();
339
355
  }
340
356
 
341
- virtual std::optional<std::string> toString() const override {
357
+ virtual std::optional<std::string>
358
+ toString(bool oneLine = false) const override {
342
359
  const esi::Type *argType = getArgType();
343
360
  const esi::Type *resultType = getResultType();
344
- return "callback " + resultType->getID() + "(" + argType->getID() + ")";
361
+ return "callback " + resultType->toString(oneLine) + "(" +
362
+ argType->toString(oneLine) + ")";
345
363
  }
346
364
 
347
365
  private:
@@ -365,37 +383,51 @@ public:
365
383
  virtual std::string getServiceSymbol() const override;
366
384
  virtual BundlePort *getPort(AppIDPath id,
367
385
  const BundleType *type) const override;
386
+ virtual Service *getChildService(Service::Type service, AppIDPath id = {},
387
+ std::string implName = {},
388
+ ServiceImplDetails details = {},
389
+ HWClientDetails clients = {}) override;
390
+ MMIO::MMIORegion *getMMIORegion() const;
368
391
 
369
392
  /// A telemetry port which gets attached to a service port.
370
- class Telemetry : public ServicePort {
393
+ class Metric : public ServicePort {
371
394
  friend class TelemetryService;
372
- Telemetry(AppID id, const BundleType *type, PortMap channels);
395
+ Metric(AppID id, const BundleType *type, PortMap channels,
396
+ const TelemetryService *telemetryService,
397
+ std::optional<uint64_t> offset);
373
398
 
374
399
  public:
375
- static Telemetry *get(AppID id, BundleType *type, WriteChannelPort &get,
376
- ReadChannelPort &data);
377
-
378
400
  void connect();
379
401
  std::future<MessageData> read();
402
+ uint64_t readInt();
380
403
 
381
- virtual std::optional<std::string> toString() const override {
404
+ virtual std::optional<std::string>
405
+ toString(bool oneLine = false) const override {
382
406
  const esi::Type *dataType =
383
407
  dynamic_cast<const ChannelType *>(type->findChannel("data").first)
384
408
  ->getInner();
385
- return "telemetry " + dataType->getID();
409
+ return "telemetry " + dataType->toString(oneLine);
386
410
  }
387
411
 
388
412
  private:
389
- WriteChannelPort *get_req;
390
- ReadChannelPort *data;
413
+ const TelemetryService *telemetryService;
414
+ MMIO::MMIORegion *mmio;
415
+ std::optional<uint64_t> offset;
391
416
  };
392
417
 
393
- const std::map<AppIDPath, Telemetry *> &getTelemetryPorts() {
394
- return telemetryPorts;
418
+ std::map<AppIDPath, Metric *> getTelemetryPorts() {
419
+ std::map<AppIDPath, Metric *> ports;
420
+ getTelemetryPorts(ports);
421
+ return ports;
395
422
  }
423
+ void getTelemetryPorts(std::map<AppIDPath, Metric *> &ports);
396
424
 
397
425
  private:
398
- mutable std::map<AppIDPath, Telemetry *> telemetryPorts;
426
+ AppIDPath id;
427
+ mutable MMIO::MMIORegion *mmio;
428
+ std::map<AppIDPath, uint64_t> portAddressAssignments;
429
+ mutable std::map<AppIDPath, Metric *> telemetryPorts;
430
+ std::list<TelemetryService *> children;
399
431
  };
400
432
 
401
433
  /// Registry of services which can be instantiated directly by the Accelerator