esiaccel 0.1.0__cp313-cp313-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.
- esiaccel/CosimBackend.dll +0 -0
- esiaccel/CosimBackend.lib +0 -0
- esiaccel/ESICppRuntime.dll +0 -0
- esiaccel/ESICppRuntime.lib +0 -0
- esiaccel/__init__.py +13 -0
- esiaccel/accelerator.py +95 -0
- esiaccel/bin/esi-cosim.py +405 -0
- esiaccel/bin/esiquery.exe +0 -0
- esiaccel/cmake/esiaccelConfig.cmake +15 -0
- esiaccel/codegen.py +197 -0
- esiaccel/cosim/Cosim_DpiPkg.sv +85 -0
- esiaccel/cosim/Cosim_Endpoint.sv +189 -0
- esiaccel/cosim/Cosim_Manifest.sv +32 -0
- esiaccel/cosim/driver.cpp +131 -0
- esiaccel/cosim/driver.sv +60 -0
- esiaccel/esiCppAccel.cp313-win_amd64.pyd +0 -0
- esiaccel/include/esi/Accelerator.h +232 -0
- esiaccel/include/esi/CLI.h +77 -0
- esiaccel/include/esi/Common.h +154 -0
- esiaccel/include/esi/Context.h +74 -0
- esiaccel/include/esi/Design.h +127 -0
- esiaccel/include/esi/Engines.h +124 -0
- esiaccel/include/esi/Logging.h +231 -0
- esiaccel/include/esi/Manifest.h +72 -0
- esiaccel/include/esi/Ports.h +275 -0
- esiaccel/include/esi/Services.h +404 -0
- esiaccel/include/esi/Types.h +182 -0
- esiaccel/include/esi/Utils.h +102 -0
- esiaccel/include/esi/backends/Cosim.h +85 -0
- esiaccel/include/esi/backends/RpcServer.h +55 -0
- esiaccel/include/esi/backends/Trace.h +87 -0
- esiaccel/lib/EsiCosimDpiServer.dll +0 -0
- esiaccel/lib/EsiCosimDpiServer.lib +0 -0
- esiaccel/lib/MtiPli.dll +0 -0
- esiaccel/lib/MtiPli.lib +0 -0
- esiaccel/types.py +512 -0
- esiaccel/utils.py +36 -0
- esiaccel/zlib1.dll +0 -0
- esiaccel-0.1.0.dist-info/METADATA +254 -0
- esiaccel-0.1.0.dist-info/RECORD +44 -0
- esiaccel-0.1.0.dist-info/WHEEL +5 -0
- esiaccel-0.1.0.dist-info/entry_points.txt +4 -0
- esiaccel-0.1.0.dist-info/licenses/LICENSE +234 -0
- esiaccel-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,275 @@
|
|
|
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) : type(type) {}
|
|
39
|
+
virtual ~ChannelPort() {}
|
|
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;
|
|
45
|
+
virtual void disconnect() = 0;
|
|
46
|
+
virtual bool isConnected() const = 0;
|
|
47
|
+
|
|
48
|
+
/// Poll for incoming data. Returns true if data was read or written into a
|
|
49
|
+
/// buffer as a result of the poll. Calling the call back could (will) also
|
|
50
|
+
/// happen in that case. Some backends need this to be called periodically. In
|
|
51
|
+
/// the usual case, this will be called by a background thread, but the ESI
|
|
52
|
+
/// runtime does not want to assume that the host processes use standard
|
|
53
|
+
/// threads. If the user wants to provide their own threads, they need to call
|
|
54
|
+
/// this on each port occasionally. This is also called from the 'master' poll
|
|
55
|
+
/// method in the Accelerator class.
|
|
56
|
+
bool poll() {
|
|
57
|
+
if (isConnected())
|
|
58
|
+
return pollImpl();
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const Type *getType() const { return type; }
|
|
63
|
+
|
|
64
|
+
protected:
|
|
65
|
+
const Type *type;
|
|
66
|
+
|
|
67
|
+
/// Method called by poll() to actually poll the channel if the channel is
|
|
68
|
+
/// connected.
|
|
69
|
+
virtual bool pollImpl() { return false; }
|
|
70
|
+
|
|
71
|
+
/// Called by all connect methods to let backends initiate the underlying
|
|
72
|
+
/// connections.
|
|
73
|
+
virtual void connectImpl(std::optional<unsigned> bufferSize) {}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/// A ChannelPort which sends data to the accelerator.
|
|
77
|
+
class WriteChannelPort : public ChannelPort {
|
|
78
|
+
public:
|
|
79
|
+
using ChannelPort::ChannelPort;
|
|
80
|
+
|
|
81
|
+
virtual void
|
|
82
|
+
connect(std::optional<unsigned> bufferSize = std::nullopt) override {
|
|
83
|
+
connectImpl(bufferSize);
|
|
84
|
+
connected = true;
|
|
85
|
+
}
|
|
86
|
+
virtual void disconnect() override { connected = false; }
|
|
87
|
+
virtual bool isConnected() const override { return connected; }
|
|
88
|
+
|
|
89
|
+
/// A very basic blocking write API. Will likely change for performance
|
|
90
|
+
/// reasons.
|
|
91
|
+
virtual void write(const MessageData &) = 0;
|
|
92
|
+
|
|
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;
|
|
97
|
+
|
|
98
|
+
private:
|
|
99
|
+
volatile bool connected = false;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/// Instantiated when a backend does not know how to create a write channel.
|
|
103
|
+
class UnknownWriteChannelPort : public WriteChannelPort {
|
|
104
|
+
public:
|
|
105
|
+
UnknownWriteChannelPort(const Type *type, std::string errmsg)
|
|
106
|
+
: WriteChannelPort(type), errmsg(errmsg) {}
|
|
107
|
+
|
|
108
|
+
void connect(std::optional<unsigned> bufferSize = std::nullopt) override {
|
|
109
|
+
throw std::runtime_error(errmsg);
|
|
110
|
+
}
|
|
111
|
+
void write(const MessageData &) override { throw std::runtime_error(errmsg); }
|
|
112
|
+
bool tryWrite(const MessageData &) override {
|
|
113
|
+
throw std::runtime_error(errmsg);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
protected:
|
|
117
|
+
std::string errmsg;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
/// A ChannelPort which reads data from the accelerator. It has two modes:
|
|
121
|
+
/// Callback and Polling which cannot be used at the same time. The mode is set
|
|
122
|
+
/// at connect() time. To change the mode, disconnect() and then connect()
|
|
123
|
+
/// again.
|
|
124
|
+
class ReadChannelPort : public ChannelPort {
|
|
125
|
+
|
|
126
|
+
public:
|
|
127
|
+
ReadChannelPort(const Type *type)
|
|
128
|
+
: ChannelPort(type), mode(Mode::Disconnected) {}
|
|
129
|
+
virtual void disconnect() override { mode = Mode::Disconnected; }
|
|
130
|
+
virtual bool isConnected() const override {
|
|
131
|
+
return mode != Mode::Disconnected;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
//===--------------------------------------------------------------------===//
|
|
135
|
+
// Callback mode: To use a callback, connect with a callback function which
|
|
136
|
+
// will get called with incoming data. This function can be called from any
|
|
137
|
+
// thread. It shall return true to indicate that the data was consumed. False
|
|
138
|
+
// if it could not accept the data and should be tried again at some point in
|
|
139
|
+
// the future. Callback is not allowed to block and needs to execute quickly.
|
|
140
|
+
//
|
|
141
|
+
// TODO: Have the callback return something upon which the caller can check,
|
|
142
|
+
// wait, and be notified.
|
|
143
|
+
//===--------------------------------------------------------------------===//
|
|
144
|
+
|
|
145
|
+
virtual void connect(std::function<bool(MessageData)> callback,
|
|
146
|
+
std::optional<unsigned> bufferSize = std::nullopt);
|
|
147
|
+
|
|
148
|
+
//===--------------------------------------------------------------------===//
|
|
149
|
+
// Polling mode methods: To use futures or blocking reads, connect without any
|
|
150
|
+
// arguments. You will then be able to use readAsync() or read().
|
|
151
|
+
//===--------------------------------------------------------------------===//
|
|
152
|
+
|
|
153
|
+
/// Default max data queue size set at connect time.
|
|
154
|
+
static constexpr uint64_t DefaultMaxDataQueueMsgs = 32;
|
|
155
|
+
|
|
156
|
+
/// Connect to the channel in polling mode.
|
|
157
|
+
virtual void
|
|
158
|
+
connect(std::optional<unsigned> bufferSize = std::nullopt) override;
|
|
159
|
+
|
|
160
|
+
/// Asynchronous read.
|
|
161
|
+
virtual std::future<MessageData> readAsync();
|
|
162
|
+
|
|
163
|
+
/// Specify a buffer to read into. Blocking. Basic API, will likely change
|
|
164
|
+
/// for performance and functionality reasons.
|
|
165
|
+
virtual void read(MessageData &outData) {
|
|
166
|
+
std::future<MessageData> f = readAsync();
|
|
167
|
+
f.wait();
|
|
168
|
+
outData = std::move(f.get());
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/// Set maximum number of messages to store in the dataQueue. 0 means no
|
|
172
|
+
/// limit. This is only used in polling mode and is set to default of 32 upon
|
|
173
|
+
/// connect. While it may seem redundant to have this and bufferSize, there
|
|
174
|
+
/// may be (and are) backends which have a very small amount of memory which
|
|
175
|
+
/// are accelerator accessible and want to move messages out as quickly as
|
|
176
|
+
/// possible.
|
|
177
|
+
void setMaxDataQueueMsgs(uint64_t maxMsgs) { maxDataQueueMsgs = maxMsgs; }
|
|
178
|
+
|
|
179
|
+
protected:
|
|
180
|
+
/// Indicates the current mode of the channel.
|
|
181
|
+
enum Mode { Disconnected, Callback, Polling };
|
|
182
|
+
volatile Mode mode;
|
|
183
|
+
|
|
184
|
+
/// Backends call this callback when new data is available.
|
|
185
|
+
std::function<bool(MessageData)> callback;
|
|
186
|
+
|
|
187
|
+
//===--------------------------------------------------------------------===//
|
|
188
|
+
// Polling mode members.
|
|
189
|
+
//===--------------------------------------------------------------------===//
|
|
190
|
+
|
|
191
|
+
/// Mutex to protect the two queues used for polling.
|
|
192
|
+
std::mutex pollingM;
|
|
193
|
+
/// Store incoming data here if there are no outstanding promises to be
|
|
194
|
+
/// fulfilled.
|
|
195
|
+
std::queue<MessageData> dataQueue;
|
|
196
|
+
/// Maximum number of messages to store in dataQueue. 0 means no limit.
|
|
197
|
+
uint64_t maxDataQueueMsgs;
|
|
198
|
+
/// Promises to be fulfilled when data is available.
|
|
199
|
+
std::queue<std::promise<MessageData>> promiseQueue;
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
/// Instantiated when a backend does not know how to create a read channel.
|
|
203
|
+
class UnknownReadChannelPort : public ReadChannelPort {
|
|
204
|
+
public:
|
|
205
|
+
UnknownReadChannelPort(const Type *type, std::string errmsg)
|
|
206
|
+
: ReadChannelPort(type), errmsg(errmsg) {}
|
|
207
|
+
|
|
208
|
+
void connect(std::function<bool(MessageData)> callback,
|
|
209
|
+
std::optional<unsigned> bufferSize = std::nullopt) override {
|
|
210
|
+
throw std::runtime_error(errmsg);
|
|
211
|
+
}
|
|
212
|
+
void connect(std::optional<unsigned> bufferSize = std::nullopt) override {
|
|
213
|
+
throw std::runtime_error(errmsg);
|
|
214
|
+
}
|
|
215
|
+
std::future<MessageData> readAsync() override {
|
|
216
|
+
throw std::runtime_error(errmsg);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
protected:
|
|
220
|
+
std::string errmsg;
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
/// Services provide connections to 'bundles' -- collections of named,
|
|
224
|
+
/// unidirectional communication channels. This class provides access to those
|
|
225
|
+
/// ChannelPorts.
|
|
226
|
+
class BundlePort {
|
|
227
|
+
public:
|
|
228
|
+
/// Compute the direction of a channel given the bundle direction and the
|
|
229
|
+
/// bundle port's direction.
|
|
230
|
+
static bool isWrite(BundleType::Direction bundleDir) {
|
|
231
|
+
return bundleDir == BundleType::Direction::To;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/// Construct a port.
|
|
235
|
+
BundlePort(AppID id, const BundleType *type, PortMap channels);
|
|
236
|
+
virtual ~BundlePort() = default;
|
|
237
|
+
|
|
238
|
+
/// Get the ID of the port.
|
|
239
|
+
AppID getID() const { return id; }
|
|
240
|
+
|
|
241
|
+
/// Get access to the raw byte streams of a channel. Intended for internal
|
|
242
|
+
/// usage and binding to other languages (e.g. Python) which have their own
|
|
243
|
+
/// message serialization code. Exposed publicly as an escape hatch, but
|
|
244
|
+
/// ordinary users should not use. You have been warned.
|
|
245
|
+
WriteChannelPort &getRawWrite(const std::string &name) const;
|
|
246
|
+
ReadChannelPort &getRawRead(const std::string &name) const;
|
|
247
|
+
const PortMap &getChannels() const { return channels; }
|
|
248
|
+
|
|
249
|
+
/// Cast this Bundle port to a subclass which is actually useful. Returns
|
|
250
|
+
/// nullptr if the cast fails.
|
|
251
|
+
// TODO: this probably shouldn't be 'const', but bundle ports' user access are
|
|
252
|
+
// const. Change that.
|
|
253
|
+
template <typename T>
|
|
254
|
+
T *getAs() const {
|
|
255
|
+
return const_cast<T *>(dynamic_cast<const T *>(this));
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/// Calls `poll` on all channels in the bundle and returns true if any of them
|
|
259
|
+
/// returned true.
|
|
260
|
+
bool poll() {
|
|
261
|
+
bool result = false;
|
|
262
|
+
for (auto &channel : channels)
|
|
263
|
+
result |= channel.second.poll();
|
|
264
|
+
return result;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
protected:
|
|
268
|
+
AppID id;
|
|
269
|
+
const BundleType *type;
|
|
270
|
+
PortMap channels;
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
} // namespace esi
|
|
274
|
+
|
|
275
|
+
#endif // ESI_PORTS_H
|
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
//===- StdServices.h - ESI standard services C++ API ------------*- 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
|
+
// The APIs in this backend are all optionally implemented. The lower level
|
|
10
|
+
// ones, however, are strongly recommended. 'Services' here refers to ESI
|
|
11
|
+
// services. These are standard APIs into the standard ESI services.
|
|
12
|
+
//
|
|
13
|
+
// DO NOT EDIT!
|
|
14
|
+
// This file is distributed as part of an ESI package. The source for this file
|
|
15
|
+
// should always be modified within CIRCT.
|
|
16
|
+
//
|
|
17
|
+
//===----------------------------------------------------------------------===//
|
|
18
|
+
|
|
19
|
+
// NOLINTNEXTLINE(llvm-header-guard)
|
|
20
|
+
#ifndef ESI_RUNTIME_SERVICES_H
|
|
21
|
+
#define ESI_RUNTIME_SERVICES_H
|
|
22
|
+
|
|
23
|
+
#include "esi/Common.h"
|
|
24
|
+
#include "esi/Context.h"
|
|
25
|
+
#include "esi/Ports.h"
|
|
26
|
+
|
|
27
|
+
#include <cstdint>
|
|
28
|
+
|
|
29
|
+
namespace esi {
|
|
30
|
+
class AcceleratorConnection;
|
|
31
|
+
class Engine;
|
|
32
|
+
namespace services {
|
|
33
|
+
|
|
34
|
+
/// Add a custom interface to a service client at a particular point in the
|
|
35
|
+
/// design hierarchy.
|
|
36
|
+
class ServicePort : public BundlePort {
|
|
37
|
+
public:
|
|
38
|
+
using BundlePort::BundlePort;
|
|
39
|
+
virtual ~ServicePort() = default;
|
|
40
|
+
// Get a description of the service port.
|
|
41
|
+
virtual std::optional<std::string> toString() const { return std::nullopt; }
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/// Parent class of all APIs modeled as 'services'. May or may not map to a
|
|
45
|
+
/// hardware side 'service'.
|
|
46
|
+
class Service {
|
|
47
|
+
public:
|
|
48
|
+
using Type = const std::type_info &;
|
|
49
|
+
Service(AcceleratorConnection &conn) : conn(conn) {}
|
|
50
|
+
virtual ~Service() = default;
|
|
51
|
+
|
|
52
|
+
virtual std::string getServiceSymbol() const = 0;
|
|
53
|
+
|
|
54
|
+
/// Create a "child" service of this service. Does not have to be the same
|
|
55
|
+
/// service type, but typically is. Used when a service already exists in the
|
|
56
|
+
/// active services table, but a new one wants to replace it. Useful for cases
|
|
57
|
+
/// where the child service needs to use the parent service. Defaults to
|
|
58
|
+
/// calling the `getService` method on `AcceleratorConnection` to get the
|
|
59
|
+
/// global service, implying that the child service does not need to use the
|
|
60
|
+
/// service it is replacing.
|
|
61
|
+
virtual Service *getChildService(Service::Type service, AppIDPath id = {},
|
|
62
|
+
std::string implName = {},
|
|
63
|
+
ServiceImplDetails details = {},
|
|
64
|
+
HWClientDetails clients = {});
|
|
65
|
+
|
|
66
|
+
/// Get specialized port for this service to attach to the given appid path.
|
|
67
|
+
/// Null returns mean nothing to attach.
|
|
68
|
+
virtual BundlePort *getPort(AppIDPath id, const BundleType *type) const {
|
|
69
|
+
return nullptr;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
AcceleratorConnection &getConnection() const { return conn; }
|
|
73
|
+
|
|
74
|
+
protected:
|
|
75
|
+
AcceleratorConnection &conn;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/// A service for which there are no standard services registered. Requires
|
|
79
|
+
/// ports be added to the design hierarchy instead of high level interfaces like
|
|
80
|
+
/// the ones in StdServices.h.
|
|
81
|
+
class CustomService : public Service {
|
|
82
|
+
public:
|
|
83
|
+
CustomService(AppIDPath idPath, AcceleratorConnection &,
|
|
84
|
+
const ServiceImplDetails &details,
|
|
85
|
+
const HWClientDetails &clients);
|
|
86
|
+
virtual ~CustomService() = default;
|
|
87
|
+
|
|
88
|
+
virtual std::string getServiceSymbol() const override {
|
|
89
|
+
return serviceSymbol;
|
|
90
|
+
}
|
|
91
|
+
virtual BundlePort *getPort(AppIDPath id,
|
|
92
|
+
const BundleType *type) const override;
|
|
93
|
+
|
|
94
|
+
protected:
|
|
95
|
+
std::string serviceSymbol;
|
|
96
|
+
AppIDPath id;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
/// Information about the Accelerator system.
|
|
100
|
+
class SysInfo : public Service {
|
|
101
|
+
public:
|
|
102
|
+
using Service::Service;
|
|
103
|
+
virtual ~SysInfo() = default;
|
|
104
|
+
|
|
105
|
+
virtual std::string getServiceSymbol() const override;
|
|
106
|
+
|
|
107
|
+
/// Get the ESI version number to check version compatibility.
|
|
108
|
+
virtual uint32_t getEsiVersion() const = 0;
|
|
109
|
+
|
|
110
|
+
/// Return the JSON-formatted system manifest.
|
|
111
|
+
virtual std::string getJsonManifest() const;
|
|
112
|
+
|
|
113
|
+
/// Return the zlib compressed JSON system manifest.
|
|
114
|
+
virtual std::vector<uint8_t> getCompressedManifest() const = 0;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
class MMIO : public Service {
|
|
118
|
+
public:
|
|
119
|
+
static constexpr std::string_view StdName = "esi.service.std.mmio";
|
|
120
|
+
|
|
121
|
+
/// Describe a region (slice) of MMIO space.
|
|
122
|
+
struct RegionDescriptor {
|
|
123
|
+
uint32_t base;
|
|
124
|
+
uint32_t size;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
MMIO(AcceleratorConnection &, const HWClientDetails &clients);
|
|
128
|
+
virtual ~MMIO() = default;
|
|
129
|
+
|
|
130
|
+
/// Read a 64-bit value from the global MMIO space.
|
|
131
|
+
virtual uint64_t read(uint32_t addr) const = 0;
|
|
132
|
+
/// Write a 64-bit value to the global MMIO space.
|
|
133
|
+
virtual void write(uint32_t addr, uint64_t data) = 0;
|
|
134
|
+
/// Get the regions of MMIO space that this service manages. Otherwise known
|
|
135
|
+
/// as the base address table.
|
|
136
|
+
const std::map<AppIDPath, RegionDescriptor> &getRegions() const {
|
|
137
|
+
return regions;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/// If the service is a MMIO service, return a region of the MMIO space which
|
|
141
|
+
/// peers into ours.
|
|
142
|
+
virtual Service *getChildService(Service::Type service, AppIDPath id = {},
|
|
143
|
+
std::string implName = {},
|
|
144
|
+
ServiceImplDetails details = {},
|
|
145
|
+
HWClientDetails clients = {}) override;
|
|
146
|
+
|
|
147
|
+
virtual std::string getServiceSymbol() const override;
|
|
148
|
+
|
|
149
|
+
/// Get a MMIO region port for a particular region descriptor.
|
|
150
|
+
virtual BundlePort *getPort(AppIDPath id,
|
|
151
|
+
const BundleType *type) const override;
|
|
152
|
+
|
|
153
|
+
private:
|
|
154
|
+
/// MMIO base address table.
|
|
155
|
+
std::map<AppIDPath, RegionDescriptor> regions;
|
|
156
|
+
|
|
157
|
+
public:
|
|
158
|
+
/// A "slice" of some parent MMIO space.
|
|
159
|
+
class MMIORegion : public ServicePort {
|
|
160
|
+
friend class MMIO;
|
|
161
|
+
MMIORegion(AppID id, MMIO *parent, RegionDescriptor desc);
|
|
162
|
+
|
|
163
|
+
public:
|
|
164
|
+
/// Get the offset (and size) of the region in the parent (usually global)
|
|
165
|
+
/// MMIO address space.
|
|
166
|
+
virtual RegionDescriptor getDescriptor() const { return desc; };
|
|
167
|
+
/// Read a 64-bit value from this region, not the global address space.
|
|
168
|
+
virtual uint64_t read(uint32_t addr) const;
|
|
169
|
+
/// Write a 64-bit value to this region, not the global address space.
|
|
170
|
+
virtual void write(uint32_t addr, uint64_t data);
|
|
171
|
+
|
|
172
|
+
virtual std::optional<std::string> toString() const override {
|
|
173
|
+
return "MMIO region " + toHex(desc.base) + " - " +
|
|
174
|
+
toHex(desc.base + desc.size);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
private:
|
|
178
|
+
MMIO *parent;
|
|
179
|
+
RegionDescriptor desc;
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
/// Implement the SysInfo API for a standard MMIO protocol.
|
|
184
|
+
class MMIOSysInfo final : public SysInfo {
|
|
185
|
+
public:
|
|
186
|
+
MMIOSysInfo(const MMIO *);
|
|
187
|
+
|
|
188
|
+
/// Get the ESI version number to check version compatibility.
|
|
189
|
+
uint32_t getEsiVersion() const override;
|
|
190
|
+
|
|
191
|
+
/// Return the zlib compressed JSON system manifest.
|
|
192
|
+
virtual std::vector<uint8_t> getCompressedManifest() const override;
|
|
193
|
+
|
|
194
|
+
private:
|
|
195
|
+
const MMIO *mmio;
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
class HostMem : public Service {
|
|
199
|
+
public:
|
|
200
|
+
static constexpr std::string_view StdName = "esi.service.std.hostmem";
|
|
201
|
+
|
|
202
|
+
using Service::Service;
|
|
203
|
+
virtual ~HostMem() = default;
|
|
204
|
+
virtual std::string getServiceSymbol() const override;
|
|
205
|
+
|
|
206
|
+
/// RAII memory region for host memory. Automatically frees the memory when
|
|
207
|
+
/// deconstructed.
|
|
208
|
+
struct HostMemRegion {
|
|
209
|
+
virtual ~HostMemRegion() = default;
|
|
210
|
+
/// Get a pointer to the host memory.
|
|
211
|
+
virtual void *getPtr() const = 0;
|
|
212
|
+
/// Sometimes the pointer the device sees is different from the pointer the
|
|
213
|
+
/// host sees. Call this functon to get the device pointer.
|
|
214
|
+
virtual void *getDevicePtr() const { return getPtr(); }
|
|
215
|
+
operator void *() const { return getPtr(); }
|
|
216
|
+
virtual std::size_t getSize() const = 0;
|
|
217
|
+
/// Flush the memory region to ensure that the device sees the latest
|
|
218
|
+
/// contents. Because some platforms require it before DMA transactions, it
|
|
219
|
+
/// is recommended to call this before any DMA on all platforms. On
|
|
220
|
+
/// platforms which don't require it, it is a cheap no-op virtual method
|
|
221
|
+
/// call.
|
|
222
|
+
virtual void flush() {}
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
/// Options for allocating host memory.
|
|
226
|
+
struct Options {
|
|
227
|
+
bool writeable = false;
|
|
228
|
+
bool useLargePages = false;
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
/// In cases where necessary, enable host memory services.
|
|
232
|
+
virtual void start() {}
|
|
233
|
+
|
|
234
|
+
/// Allocate a region of host memory in accelerator accessible address space.
|
|
235
|
+
virtual std::unique_ptr<HostMemRegion> allocate(std::size_t size,
|
|
236
|
+
Options opts) const = 0;
|
|
237
|
+
|
|
238
|
+
/// Try to make a region of host memory accessible to the accelerator. Returns
|
|
239
|
+
/// 'false' on failure. It is optional for an accelerator backend to implement
|
|
240
|
+
/// this, so client code needs to have a fallback for when this returns
|
|
241
|
+
/// 'false'. On success, it is the client's responsibility to ensure that the
|
|
242
|
+
/// memory eventually gets unmapped.
|
|
243
|
+
virtual bool mapMemory(void *ptr, std::size_t size, Options opts) const {
|
|
244
|
+
return false;
|
|
245
|
+
}
|
|
246
|
+
/// Unmap memory which was previously mapped with 'mapMemory'. Undefined
|
|
247
|
+
/// behavior when called with a pointer which was not previously mapped.
|
|
248
|
+
virtual void unmapMemory(void *ptr) const {}
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
/// Service for calling functions.
|
|
252
|
+
class FuncService : public Service {
|
|
253
|
+
public:
|
|
254
|
+
FuncService(AppIDPath id, AcceleratorConnection &, ServiceImplDetails details,
|
|
255
|
+
HWClientDetails clients);
|
|
256
|
+
|
|
257
|
+
virtual std::string getServiceSymbol() const override;
|
|
258
|
+
virtual BundlePort *getPort(AppIDPath id,
|
|
259
|
+
const BundleType *type) const override;
|
|
260
|
+
|
|
261
|
+
/// A function call which gets attached to a service port.
|
|
262
|
+
class Function : public ServicePort {
|
|
263
|
+
friend class FuncService;
|
|
264
|
+
using ServicePort::ServicePort;
|
|
265
|
+
|
|
266
|
+
public:
|
|
267
|
+
static Function *get(AppID id, BundleType *type, WriteChannelPort &arg,
|
|
268
|
+
ReadChannelPort &result);
|
|
269
|
+
|
|
270
|
+
void connect();
|
|
271
|
+
std::future<MessageData> call(const MessageData &arg);
|
|
272
|
+
|
|
273
|
+
virtual std::optional<std::string> toString() const override {
|
|
274
|
+
const esi::Type *argType =
|
|
275
|
+
dynamic_cast<const ChannelType *>(type->findChannel("arg").first)
|
|
276
|
+
->getInner();
|
|
277
|
+
const esi::Type *resultType =
|
|
278
|
+
dynamic_cast<const ChannelType *>(type->findChannel("result").first)
|
|
279
|
+
->getInner();
|
|
280
|
+
return "function " + resultType->getID() + "(" + argType->getID() + ")";
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
private:
|
|
284
|
+
std::mutex callMutex;
|
|
285
|
+
WriteChannelPort *arg;
|
|
286
|
+
ReadChannelPort *result;
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
private:
|
|
290
|
+
std::string symbol;
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
/// Service for servicing function calls from the accelerator.
|
|
294
|
+
class CallService : public Service {
|
|
295
|
+
public:
|
|
296
|
+
CallService(AcceleratorConnection &acc, AppIDPath id,
|
|
297
|
+
ServiceImplDetails details);
|
|
298
|
+
|
|
299
|
+
virtual std::string getServiceSymbol() const override;
|
|
300
|
+
virtual BundlePort *getPort(AppIDPath id,
|
|
301
|
+
const BundleType *type) const override;
|
|
302
|
+
|
|
303
|
+
/// A function call which gets attached to a service port.
|
|
304
|
+
class Callback : public ServicePort {
|
|
305
|
+
friend class CallService;
|
|
306
|
+
Callback(AcceleratorConnection &acc, AppID id, const BundleType *,
|
|
307
|
+
PortMap channels);
|
|
308
|
+
|
|
309
|
+
public:
|
|
310
|
+
static Callback *get(AcceleratorConnection &acc, AppID id, BundleType *type,
|
|
311
|
+
WriteChannelPort &result, ReadChannelPort &arg);
|
|
312
|
+
|
|
313
|
+
/// Connect a callback to code which will be executed when the accelerator
|
|
314
|
+
/// invokes the callback. The 'quick' flag indicates that the callback is
|
|
315
|
+
/// sufficiently fast that it could be called in the same thread as the
|
|
316
|
+
/// port callback.
|
|
317
|
+
void connect(std::function<MessageData(const MessageData &)> callback,
|
|
318
|
+
bool quick = false);
|
|
319
|
+
|
|
320
|
+
virtual std::optional<std::string> toString() const override {
|
|
321
|
+
const esi::Type *argType =
|
|
322
|
+
dynamic_cast<const ChannelType *>(type->findChannel("arg").first)
|
|
323
|
+
->getInner();
|
|
324
|
+
const esi::Type *resultType =
|
|
325
|
+
dynamic_cast<const ChannelType *>(type->findChannel("result").first)
|
|
326
|
+
->getInner();
|
|
327
|
+
return "callback " + resultType->getID() + "(" + argType->getID() + ")";
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
private:
|
|
331
|
+
ReadChannelPort *arg;
|
|
332
|
+
WriteChannelPort *result;
|
|
333
|
+
AcceleratorConnection &acc;
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
private:
|
|
337
|
+
std::string symbol;
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
/// Service for retrieving telemetry data from the accelerator.
|
|
341
|
+
class TelemetryService : public Service {
|
|
342
|
+
public:
|
|
343
|
+
static constexpr std::string_view StdName = "esi.service.std.telemetry";
|
|
344
|
+
|
|
345
|
+
TelemetryService(AppIDPath id, AcceleratorConnection &,
|
|
346
|
+
ServiceImplDetails details, HWClientDetails clients);
|
|
347
|
+
|
|
348
|
+
virtual std::string getServiceSymbol() const override;
|
|
349
|
+
virtual BundlePort *getPort(AppIDPath id,
|
|
350
|
+
const BundleType *type) const override;
|
|
351
|
+
|
|
352
|
+
/// A telemetry port which gets attached to a service port.
|
|
353
|
+
class Telemetry : public ServicePort {
|
|
354
|
+
friend class TelemetryService;
|
|
355
|
+
Telemetry(AppID id, const BundleType *type, PortMap channels);
|
|
356
|
+
|
|
357
|
+
public:
|
|
358
|
+
static Telemetry *get(AppID id, BundleType *type, WriteChannelPort &get,
|
|
359
|
+
ReadChannelPort &data);
|
|
360
|
+
|
|
361
|
+
void connect();
|
|
362
|
+
std::future<MessageData> read();
|
|
363
|
+
|
|
364
|
+
virtual std::optional<std::string> toString() const override {
|
|
365
|
+
const esi::Type *dataType =
|
|
366
|
+
dynamic_cast<const ChannelType *>(type->findChannel("data").first)
|
|
367
|
+
->getInner();
|
|
368
|
+
return "telemetry " + dataType->getID();
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
private:
|
|
372
|
+
WriteChannelPort *get_req;
|
|
373
|
+
ReadChannelPort *data;
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
const std::map<AppIDPath, Telemetry *> &getTelemetryPorts() {
|
|
377
|
+
return telemetryPorts;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
private:
|
|
381
|
+
mutable std::map<AppIDPath, Telemetry *> telemetryPorts;
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
/// Registry of services which can be instantiated directly by the Accelerator
|
|
385
|
+
/// class if the backend doesn't do anything special with a service.
|
|
386
|
+
class ServiceRegistry {
|
|
387
|
+
public:
|
|
388
|
+
/// Create a service instance from the given details. Returns nullptr if
|
|
389
|
+
/// 'svcType' isn't registered.
|
|
390
|
+
static Service *createService(AcceleratorConnection *acc,
|
|
391
|
+
Service::Type svcType, AppIDPath id,
|
|
392
|
+
std::string implName,
|
|
393
|
+
ServiceImplDetails details,
|
|
394
|
+
HWClientDetails clients);
|
|
395
|
+
|
|
396
|
+
/// Resolve a service type from a string. If the string isn't recognized,
|
|
397
|
+
/// default to CustomService.
|
|
398
|
+
static Service::Type lookupServiceType(const std::string &);
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
} // namespace services
|
|
402
|
+
} // namespace esi
|
|
403
|
+
|
|
404
|
+
#endif // ESI_RUNTIME_SERVICES_H
|