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.
- 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 +31 -0
- esiaccel/abseil_dll.dll +0 -0
- esiaccel/accelerator.py +134 -0
- esiaccel/cares.dll +0 -0
- esiaccel/cmake/esiaccelConfig.cmake +49 -0
- esiaccel/codegen.py +197 -0
- esiaccel/cosim/Cosim_DpiPkg.sv +85 -0
- esiaccel/cosim/Cosim_Endpoint.sv +218 -0
- esiaccel/cosim/Cosim_Manifest.sv +32 -0
- esiaccel/cosim/driver.cpp +131 -0
- esiaccel/cosim/driver.sv +74 -0
- esiaccel/cosim/questa.py +141 -0
- esiaccel/cosim/simulator.py +382 -0
- esiaccel/cosim/verilator.py +92 -0
- esiaccel/esi-cosim.py +104 -0
- esiaccel/esiCppAccel.cp312-win_amd64.pyd +0 -0
- esiaccel/esiquery.exe +0 -0
- esiaccel/include/esi/Accelerator.h +219 -0
- esiaccel/include/esi/CLI.h +77 -0
- esiaccel/include/esi/Common.h +182 -0
- esiaccel/include/esi/Context.h +82 -0
- esiaccel/include/esi/Design.h +132 -0
- esiaccel/include/esi/Engines.h +124 -0
- esiaccel/include/esi/Logging.h +231 -0
- esiaccel/include/esi/Manifest.h +70 -0
- esiaccel/include/esi/Ports.h +482 -0
- esiaccel/include/esi/Services.h +453 -0
- esiaccel/include/esi/Types.h +334 -0
- esiaccel/include/esi/Utils.h +102 -0
- esiaccel/include/esi/Values.h +313 -0
- esiaccel/include/esi/backends/Cosim.h +78 -0
- esiaccel/include/esi/backends/RpcClient.h +97 -0
- esiaccel/include/esi/backends/RpcServer.h +73 -0
- esiaccel/include/esi/backends/Trace.h +87 -0
- 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 +565 -0
- esiaccel/utils.py +54 -0
- esiaccel/zlib1.dll +0 -0
- esiaccel-0.2.2.dist-info/METADATA +254 -0
- esiaccel-0.2.2.dist-info/RECORD +57 -0
- esiaccel-0.2.2.dist-info/WHEEL +5 -0
- esiaccel-0.2.2.dist-info/entry_points.txt +4 -0
- esiaccel-0.2.2.dist-info/licenses/LICENSE +234 -0
- esiaccel-0.2.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
//===- Accelerator.h - Base ESI runtime 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
|
+
// Basic ESI APIs. The 'Accelerator' class is the superclass for all accelerator
|
|
10
|
+
// backends. It should (usually) provide enough functionality such that users do
|
|
11
|
+
// not have to interact with the platform-specific backend implementation with
|
|
12
|
+
// the exception of connecting to the accelerator.
|
|
13
|
+
//
|
|
14
|
+
// DO NOT EDIT!
|
|
15
|
+
// This file is distributed as part of an ESI package. The source for this file
|
|
16
|
+
// should always be modified within CIRCT.
|
|
17
|
+
//
|
|
18
|
+
//===----------------------------------------------------------------------===//
|
|
19
|
+
|
|
20
|
+
// NOLINTNEXTLINE(llvm-header-guard)
|
|
21
|
+
#ifndef ESI_ACCELERATOR_H
|
|
22
|
+
#define ESI_ACCELERATOR_H
|
|
23
|
+
|
|
24
|
+
#include "esi/Context.h"
|
|
25
|
+
#include "esi/Design.h"
|
|
26
|
+
#include "esi/Engines.h"
|
|
27
|
+
#include "esi/Manifest.h"
|
|
28
|
+
#include "esi/Ports.h"
|
|
29
|
+
#include "esi/Services.h"
|
|
30
|
+
|
|
31
|
+
#include <functional>
|
|
32
|
+
#include <map>
|
|
33
|
+
#include <memory>
|
|
34
|
+
#include <string>
|
|
35
|
+
#include <typeinfo>
|
|
36
|
+
|
|
37
|
+
namespace esi {
|
|
38
|
+
// Forward declarations.
|
|
39
|
+
class AcceleratorServiceThread;
|
|
40
|
+
|
|
41
|
+
//===----------------------------------------------------------------------===//
|
|
42
|
+
// Constants used by low-level APIs.
|
|
43
|
+
//===----------------------------------------------------------------------===//
|
|
44
|
+
|
|
45
|
+
constexpr uint32_t MetadataOffset = 8;
|
|
46
|
+
constexpr uint64_t MagicNumberLo = 0xE5100E51;
|
|
47
|
+
constexpr uint64_t MagicNumberHi = 0x207D98E5;
|
|
48
|
+
constexpr uint64_t MagicNumber = MagicNumberLo | (MagicNumberHi << 32);
|
|
49
|
+
constexpr uint32_t ExpectedVersionNumber = 0;
|
|
50
|
+
|
|
51
|
+
//===----------------------------------------------------------------------===//
|
|
52
|
+
// Accelerator design hierarchy root.
|
|
53
|
+
//===----------------------------------------------------------------------===//
|
|
54
|
+
|
|
55
|
+
/// Top level accelerator class. Maintains a shared pointer to the manifest,
|
|
56
|
+
/// which owns objects used in the design hierarchy owned by this class. Since
|
|
57
|
+
/// this class owns the entire design hierarchy, when it gets destroyed the
|
|
58
|
+
/// entire design hierarchy gets destroyed so all of the instances, ports, etc.
|
|
59
|
+
/// are no longer valid pointers.
|
|
60
|
+
class Accelerator : public HWModule {
|
|
61
|
+
public:
|
|
62
|
+
Accelerator() = delete;
|
|
63
|
+
Accelerator(const Accelerator &) = delete;
|
|
64
|
+
~Accelerator() = default;
|
|
65
|
+
Accelerator(std::optional<ModuleInfo> info,
|
|
66
|
+
std::vector<std::unique_ptr<Instance>> children,
|
|
67
|
+
std::vector<services::Service *> services,
|
|
68
|
+
std::vector<std::unique_ptr<BundlePort>> &&ports)
|
|
69
|
+
: HWModule(info, std::move(children), services, std::move(ports)) {}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
//===----------------------------------------------------------------------===//
|
|
73
|
+
// Connection to the accelerator and its services.
|
|
74
|
+
//===----------------------------------------------------------------------===//
|
|
75
|
+
|
|
76
|
+
/// Abstract class representing a connection to an accelerator. Actual
|
|
77
|
+
/// connections (e.g. to a co-simulation or actual device) are implemented by
|
|
78
|
+
/// subclasses. No methods in here are thread safe.
|
|
79
|
+
class AcceleratorConnection {
|
|
80
|
+
public:
|
|
81
|
+
AcceleratorConnection(Context &ctxt);
|
|
82
|
+
virtual ~AcceleratorConnection();
|
|
83
|
+
Context &getCtxt() const { return ctxt; }
|
|
84
|
+
Logger &getLogger() const { return ctxt.getLogger(); }
|
|
85
|
+
|
|
86
|
+
/// Disconnect from the accelerator cleanly.
|
|
87
|
+
virtual void disconnect();
|
|
88
|
+
|
|
89
|
+
/// Return a pointer to the accelerator 'service' thread (or threads). If the
|
|
90
|
+
/// thread(s) are not running, they will be started when this method is
|
|
91
|
+
/// called. `std::thread` is used. If users don't want the runtime to spin up
|
|
92
|
+
/// threads, don't call this method. `AcceleratorServiceThread` is owned by
|
|
93
|
+
/// AcceleratorConnection and governed by the lifetime of the this object.
|
|
94
|
+
AcceleratorServiceThread *getServiceThread();
|
|
95
|
+
|
|
96
|
+
using Service = services::Service;
|
|
97
|
+
/// Get a typed reference to a particular service type. Caller does *not* take
|
|
98
|
+
/// ownership of the returned pointer -- the Accelerator object owns it.
|
|
99
|
+
/// Pointer lifetime ends with the Accelerator lifetime.
|
|
100
|
+
template <typename ServiceClass>
|
|
101
|
+
ServiceClass *getService(AppIDPath id = {}, std::string implName = {},
|
|
102
|
+
ServiceImplDetails details = {},
|
|
103
|
+
HWClientDetails clients = {}) {
|
|
104
|
+
return dynamic_cast<ServiceClass *>(
|
|
105
|
+
getService(typeid(ServiceClass), id, implName, details, clients));
|
|
106
|
+
}
|
|
107
|
+
/// Calls `createService` and caches the result. Subclasses can override if
|
|
108
|
+
/// they want to use their own caching mechanism.
|
|
109
|
+
virtual Service *getService(Service::Type service, AppIDPath id = {},
|
|
110
|
+
std::string implName = {},
|
|
111
|
+
ServiceImplDetails details = {},
|
|
112
|
+
HWClientDetails clients = {});
|
|
113
|
+
|
|
114
|
+
/// Assume ownership of an accelerator object. Ties the lifetime of the
|
|
115
|
+
/// accelerator to this connection. Returns a raw pointer to the object.
|
|
116
|
+
Accelerator *takeOwnership(std::unique_ptr<Accelerator> accel);
|
|
117
|
+
|
|
118
|
+
/// Create a new engine for channel communication with the accelerator. The
|
|
119
|
+
/// default is to call the global `createEngine` to get an engine which has
|
|
120
|
+
/// registered itself. Individual accelerator connection backends can override
|
|
121
|
+
/// this to customize behavior.
|
|
122
|
+
virtual void createEngine(const std::string &engineTypeName, AppIDPath idPath,
|
|
123
|
+
const ServiceImplDetails &details,
|
|
124
|
+
const HWClientDetails &clients);
|
|
125
|
+
virtual const BundleEngineMap &getEngineMapFor(AppIDPath id) {
|
|
126
|
+
return clientEngines[id];
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
Accelerator &getAccelerator() {
|
|
130
|
+
if (!ownedAccelerator)
|
|
131
|
+
throw std::runtime_error(
|
|
132
|
+
"AcceleratorConnection does not own an accelerator");
|
|
133
|
+
return *ownedAccelerator;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
protected:
|
|
137
|
+
/// If `createEngine` is overridden, this method should be called to register
|
|
138
|
+
/// the engine and all of the channels it services.
|
|
139
|
+
void registerEngine(AppIDPath idPath, std::unique_ptr<Engine> engine,
|
|
140
|
+
const HWClientDetails &clients);
|
|
141
|
+
|
|
142
|
+
/// Called by `getServiceImpl` exclusively. It wraps the pointer returned by
|
|
143
|
+
/// this in a unique_ptr and caches it. Separate this from the
|
|
144
|
+
/// wrapping/caching since wrapping/caching is an implementation detail.
|
|
145
|
+
virtual Service *createService(Service::Type service, AppIDPath idPath,
|
|
146
|
+
std::string implName,
|
|
147
|
+
const ServiceImplDetails &details,
|
|
148
|
+
const HWClientDetails &clients) = 0;
|
|
149
|
+
|
|
150
|
+
/// Collection of owned engines.
|
|
151
|
+
std::map<AppIDPath, std::unique_ptr<Engine>> ownedEngines;
|
|
152
|
+
/// Mapping of clients to their servicing engines.
|
|
153
|
+
std::map<AppIDPath, BundleEngineMap> clientEngines;
|
|
154
|
+
|
|
155
|
+
private:
|
|
156
|
+
/// ESI accelerator context.
|
|
157
|
+
Context &ctxt;
|
|
158
|
+
|
|
159
|
+
/// Cache services via a unique_ptr so they get free'd automatically when
|
|
160
|
+
/// Accelerator objects get deconstructed.
|
|
161
|
+
using ServiceCacheKey = std::tuple<std::string, AppIDPath>;
|
|
162
|
+
std::map<ServiceCacheKey, std::unique_ptr<Service>> serviceCache;
|
|
163
|
+
|
|
164
|
+
std::unique_ptr<AcceleratorServiceThread> serviceThread;
|
|
165
|
+
|
|
166
|
+
/// Accelerator object owned by this connection.
|
|
167
|
+
std::unique_ptr<Accelerator> ownedAccelerator;
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
namespace registry {
|
|
171
|
+
|
|
172
|
+
namespace internal {
|
|
173
|
+
|
|
174
|
+
/// Backends can register themselves to be connected via a connection string.
|
|
175
|
+
using BackendCreate = std::function<std::unique_ptr<AcceleratorConnection>(
|
|
176
|
+
Context &, std::string)>;
|
|
177
|
+
void registerBackend(const std::string &name, BackendCreate create);
|
|
178
|
+
|
|
179
|
+
// Helper struct to
|
|
180
|
+
template <typename TAccelerator>
|
|
181
|
+
struct RegisterAccelerator {
|
|
182
|
+
RegisterAccelerator(const char *name) {
|
|
183
|
+
registerBackend(name, &TAccelerator::connect);
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
#define REGISTER_ACCELERATOR(Name, TAccelerator) \
|
|
188
|
+
static ::esi::registry::internal::RegisterAccelerator<TAccelerator> \
|
|
189
|
+
__register_accel____LINE__(Name)
|
|
190
|
+
|
|
191
|
+
} // namespace internal
|
|
192
|
+
} // namespace registry
|
|
193
|
+
|
|
194
|
+
/// Background thread which services various requests. Currently, it listens on
|
|
195
|
+
/// ports and calls callbacks for incoming messages on said ports.
|
|
196
|
+
class AcceleratorServiceThread {
|
|
197
|
+
public:
|
|
198
|
+
AcceleratorServiceThread();
|
|
199
|
+
~AcceleratorServiceThread();
|
|
200
|
+
|
|
201
|
+
/// When there's data on any of the listenPorts, call the callback. Callable
|
|
202
|
+
/// from any thread.
|
|
203
|
+
void
|
|
204
|
+
addListener(std::initializer_list<ReadChannelPort *> listenPorts,
|
|
205
|
+
std::function<void(ReadChannelPort *, MessageData)> callback);
|
|
206
|
+
|
|
207
|
+
/// Poll this module.
|
|
208
|
+
void addPoll(HWModule &module);
|
|
209
|
+
|
|
210
|
+
/// Instruct the service thread to stop running.
|
|
211
|
+
void stop();
|
|
212
|
+
|
|
213
|
+
private:
|
|
214
|
+
struct Impl;
|
|
215
|
+
std::unique_ptr<Impl> impl;
|
|
216
|
+
};
|
|
217
|
+
} // namespace esi
|
|
218
|
+
|
|
219
|
+
#endif // ESI_ACCELERATOR_H
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
//===- CLI.h - ESI runtime tool CLI parser common ---------------*- 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
|
+
// This file contains the common CLI parser code for ESI runtime tools. Exposed
|
|
10
|
+
// publicly so that out-of-tree tools can use it. This is a header-only library
|
|
11
|
+
// to make compilation easier for out-of-tree tools.
|
|
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 (lib/dialect/ESI/runtime/cpp).
|
|
16
|
+
//
|
|
17
|
+
//===----------------------------------------------------------------------===//
|
|
18
|
+
|
|
19
|
+
// NOLINTNEXTLINE(llvm-header-guard)
|
|
20
|
+
#ifndef ESI_CLI_H
|
|
21
|
+
#define ESI_CLI_H
|
|
22
|
+
|
|
23
|
+
#include "CLI/CLI.hpp"
|
|
24
|
+
#include "esi/Context.h"
|
|
25
|
+
|
|
26
|
+
namespace esi {
|
|
27
|
+
|
|
28
|
+
/// Common options and code for ESI runtime tools.
|
|
29
|
+
class CliParser : public CLI::App {
|
|
30
|
+
public:
|
|
31
|
+
CliParser(const std::string &toolName)
|
|
32
|
+
: CLI::App(toolName), debug(false), verbose(false) {
|
|
33
|
+
add_option("backend", backend, "Backend to use for connection")->required();
|
|
34
|
+
add_option("connection", connStr,
|
|
35
|
+
"Connection string to use for accelerator communication")
|
|
36
|
+
->required();
|
|
37
|
+
add_flag("--debug", debug, "Enable debug logging");
|
|
38
|
+
#ifdef ESI_RUNTIME_TRACE
|
|
39
|
+
add_flag("--trace", trace, "Enable trace logging");
|
|
40
|
+
#endif
|
|
41
|
+
add_flag("-v,--verbose", verbose, "Enable verbose (info) logging");
|
|
42
|
+
require_subcommand(0, 1);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/// Run the parser.
|
|
46
|
+
int esiParse(int argc, const char **argv) {
|
|
47
|
+
CLI11_PARSE(*this, argc, argv);
|
|
48
|
+
if (trace)
|
|
49
|
+
ctxt = Context::withLogger<ConsoleLogger>(Logger::Level::Trace);
|
|
50
|
+
else if (debug)
|
|
51
|
+
ctxt = Context::withLogger<ConsoleLogger>(Logger::Level::Debug);
|
|
52
|
+
else if (verbose)
|
|
53
|
+
ctxt = Context::withLogger<ConsoleLogger>(Logger::Level::Info);
|
|
54
|
+
else
|
|
55
|
+
ctxt = Context::withLogger<ConsoleLogger>(Logger::Level::Warning);
|
|
56
|
+
return 0;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/// Connect to the accelerator using the specified backend and connection.
|
|
60
|
+
AcceleratorConnection *connect() { return ctxt->connect(backend, connStr); }
|
|
61
|
+
|
|
62
|
+
/// Get the context.
|
|
63
|
+
Context &getContext() { return *ctxt; }
|
|
64
|
+
|
|
65
|
+
protected:
|
|
66
|
+
std::unique_ptr<Context> ctxt;
|
|
67
|
+
|
|
68
|
+
std::string backend;
|
|
69
|
+
std::string connStr;
|
|
70
|
+
bool trace = false;
|
|
71
|
+
bool debug = false;
|
|
72
|
+
bool verbose = false;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
} // namespace esi
|
|
76
|
+
|
|
77
|
+
#endif // ESI_CLI_H
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
//===- Common.h - Commonly used classes w/o dependencies --------*- 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_COMMON_H
|
|
17
|
+
#define ESI_COMMON_H
|
|
18
|
+
|
|
19
|
+
#include <any>
|
|
20
|
+
#include <cstdint>
|
|
21
|
+
#include <map>
|
|
22
|
+
#include <optional>
|
|
23
|
+
#include <span>
|
|
24
|
+
#include <stdexcept>
|
|
25
|
+
#include <string>
|
|
26
|
+
#include <vector>
|
|
27
|
+
|
|
28
|
+
namespace esi {
|
|
29
|
+
class Type;
|
|
30
|
+
|
|
31
|
+
//===----------------------------------------------------------------------===//
|
|
32
|
+
// Common accelerator description types.
|
|
33
|
+
//===----------------------------------------------------------------------===//
|
|
34
|
+
|
|
35
|
+
struct AppID {
|
|
36
|
+
std::string name;
|
|
37
|
+
std::optional<uint32_t> idx;
|
|
38
|
+
|
|
39
|
+
AppID(const std::string &name, std::optional<uint32_t> idx = std::nullopt)
|
|
40
|
+
: name(name), idx(idx) {}
|
|
41
|
+
|
|
42
|
+
bool operator==(const AppID &other) const {
|
|
43
|
+
return name == other.name && idx == other.idx;
|
|
44
|
+
}
|
|
45
|
+
bool operator!=(const AppID &other) const { return !(*this == other); }
|
|
46
|
+
friend std::ostream &operator<<(std::ostream &os, const AppID &id);
|
|
47
|
+
|
|
48
|
+
std::string toString() const {
|
|
49
|
+
if (idx.has_value())
|
|
50
|
+
return name + "[" + std::to_string(idx.value()) + "]";
|
|
51
|
+
return name;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
bool operator<(const AppID &a, const AppID &b);
|
|
55
|
+
|
|
56
|
+
class AppIDPath : public std::vector<AppID> {
|
|
57
|
+
public:
|
|
58
|
+
using std::vector<AppID>::vector;
|
|
59
|
+
|
|
60
|
+
AppIDPath operator+(const AppIDPath &b) const;
|
|
61
|
+
AppIDPath parent() const;
|
|
62
|
+
std::string toStr() const;
|
|
63
|
+
friend std::ostream &operator<<(std::ostream &os, const AppIDPath &path);
|
|
64
|
+
};
|
|
65
|
+
bool operator<(const AppIDPath &a, const AppIDPath &b);
|
|
66
|
+
|
|
67
|
+
struct Constant {
|
|
68
|
+
std::any value;
|
|
69
|
+
std::optional<const Type *> type;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
struct ModuleInfo {
|
|
73
|
+
std::optional<std::string> name;
|
|
74
|
+
std::optional<std::string> summary;
|
|
75
|
+
std::optional<std::string> version;
|
|
76
|
+
std::optional<std::string> repo;
|
|
77
|
+
std::optional<std::string> commitHash;
|
|
78
|
+
std::map<std::string, Constant> constants;
|
|
79
|
+
std::map<std::string, std::any> extra;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
/// A description of a service port. Used pretty exclusively in setting up the
|
|
83
|
+
/// design.
|
|
84
|
+
struct ServicePortDesc {
|
|
85
|
+
std::string name;
|
|
86
|
+
std::string portName;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/// Details about how to connect to a particular channel.
|
|
90
|
+
struct ChannelAssignment {
|
|
91
|
+
/// The name of the type of connection. Typically, the name of the DMA engine
|
|
92
|
+
/// or "cosim" if a cosimulation channel is being used.
|
|
93
|
+
std::string type;
|
|
94
|
+
/// Implementation-specific options.
|
|
95
|
+
std::map<std::string, std::any> implOptions;
|
|
96
|
+
};
|
|
97
|
+
using ChannelAssignments = std::map<std::string, ChannelAssignment>;
|
|
98
|
+
|
|
99
|
+
/// A description of a hardware client. Used pretty exclusively in setting up
|
|
100
|
+
/// the design.
|
|
101
|
+
struct HWClientDetail {
|
|
102
|
+
AppIDPath relPath;
|
|
103
|
+
ServicePortDesc port;
|
|
104
|
+
ChannelAssignments channelAssignments;
|
|
105
|
+
std::map<std::string, std::any> implOptions;
|
|
106
|
+
};
|
|
107
|
+
using HWClientDetails = std::vector<HWClientDetail>;
|
|
108
|
+
using ServiceImplDetails = std::map<std::string, std::any>;
|
|
109
|
+
|
|
110
|
+
/// A logical chunk of data representing serialized data. Currently, just a
|
|
111
|
+
/// wrapper for a vector of bytes, which is not efficient in terms of memory
|
|
112
|
+
/// copying. This will change in the future as will the API.
|
|
113
|
+
class MessageData {
|
|
114
|
+
public:
|
|
115
|
+
/// Adopts the data vector buffer.
|
|
116
|
+
MessageData() = default;
|
|
117
|
+
MessageData(std::span<const uint8_t> data)
|
|
118
|
+
: data(data.data(), data.data() + data.size()) {}
|
|
119
|
+
MessageData(std::vector<uint8_t> &data) : data(std::move(data)) {}
|
|
120
|
+
MessageData(std::vector<uint8_t> &&data) : data(std::move(data)) {}
|
|
121
|
+
MessageData(const uint8_t *data, size_t size) : data(data, data + size) {}
|
|
122
|
+
~MessageData() = default;
|
|
123
|
+
|
|
124
|
+
const uint8_t *getBytes() const { return data.data(); }
|
|
125
|
+
|
|
126
|
+
/// Get the data as a vector of bytes.
|
|
127
|
+
const std::vector<uint8_t> &getData() const { return data; }
|
|
128
|
+
|
|
129
|
+
/// Implicit conversion to a vector/span of bytes, to play nice with other
|
|
130
|
+
/// APIs that accept bytearray-like things.
|
|
131
|
+
operator const std::vector<uint8_t> &() const { return data; }
|
|
132
|
+
operator std::span<const uint8_t>() const { return data; }
|
|
133
|
+
|
|
134
|
+
/// Move the data out of this object.
|
|
135
|
+
std::vector<uint8_t> takeData() { return std::move(data); }
|
|
136
|
+
|
|
137
|
+
/// Get the size of the data in bytes.
|
|
138
|
+
size_t getSize() const { return data.size(); }
|
|
139
|
+
size_t size() const { return getSize(); }
|
|
140
|
+
|
|
141
|
+
/// Returns true if this message contains no data.
|
|
142
|
+
bool empty() const { return data.empty(); }
|
|
143
|
+
|
|
144
|
+
/// Cast to a type. Throws if the size of the data does not match the size of
|
|
145
|
+
/// the message. The lifetime of the resulting pointer is tied to the lifetime
|
|
146
|
+
/// of this object.
|
|
147
|
+
template <typename T>
|
|
148
|
+
const T *as() const {
|
|
149
|
+
if (data.size() != sizeof(T))
|
|
150
|
+
throw std::runtime_error("Data size does not match type size. Size is " +
|
|
151
|
+
std::to_string(data.size()) + ", expected " +
|
|
152
|
+
std::to_string(sizeof(T)) + ".");
|
|
153
|
+
return reinterpret_cast<const T *>(data.data());
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/// Cast from a type to its raw bytes.
|
|
157
|
+
template <typename T>
|
|
158
|
+
static MessageData from(T &t) {
|
|
159
|
+
return MessageData(reinterpret_cast<const uint8_t *>(&t), sizeof(T));
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/// Convert the data to a hex string.
|
|
163
|
+
std::string toHex() const;
|
|
164
|
+
|
|
165
|
+
private:
|
|
166
|
+
std::vector<uint8_t> data;
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
} // namespace esi
|
|
170
|
+
|
|
171
|
+
std::ostream &operator<<(std::ostream &, const esi::ModuleInfo &);
|
|
172
|
+
|
|
173
|
+
//===----------------------------------------------------------------------===//
|
|
174
|
+
// Functions which should be in the standard library.
|
|
175
|
+
//===----------------------------------------------------------------------===//
|
|
176
|
+
|
|
177
|
+
namespace esi {
|
|
178
|
+
std::string toHex(void *val);
|
|
179
|
+
std::string toHex(uint64_t val);
|
|
180
|
+
} // namespace esi
|
|
181
|
+
|
|
182
|
+
#endif // ESI_COMMON_H
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
//===- Context.h - Accelerator context --------------------------*- 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_CONTEXT_H
|
|
17
|
+
#define ESI_CONTEXT_H
|
|
18
|
+
|
|
19
|
+
#include "esi/Logging.h"
|
|
20
|
+
#include "esi/Types.h"
|
|
21
|
+
|
|
22
|
+
#include <exception>
|
|
23
|
+
#include <map>
|
|
24
|
+
#include <memory>
|
|
25
|
+
#include <vector>
|
|
26
|
+
|
|
27
|
+
namespace esi {
|
|
28
|
+
class AcceleratorConnection;
|
|
29
|
+
|
|
30
|
+
/// AcceleratorConnections, Accelerators, and Manifests must all share a
|
|
31
|
+
/// context. It owns all the types, uniquifying them. It also owns the
|
|
32
|
+
/// connections (which own the Accelerators). When it is destroyed, all
|
|
33
|
+
/// connections are disconnected and the objects are destroyed.
|
|
34
|
+
class Context {
|
|
35
|
+
public:
|
|
36
|
+
Context();
|
|
37
|
+
Context(std::unique_ptr<Logger> logger);
|
|
38
|
+
~Context();
|
|
39
|
+
|
|
40
|
+
/// Disconnect from all accelerators associated with this context.
|
|
41
|
+
void disconnectAll();
|
|
42
|
+
|
|
43
|
+
/// Create a context with a specific logger type.
|
|
44
|
+
template <typename T, typename... Args>
|
|
45
|
+
static std::unique_ptr<Context> withLogger(Args &&...args) {
|
|
46
|
+
return std::make_unique<Context>(std::make_unique<T>(args...));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/// Resolve a type id to the type.
|
|
50
|
+
std::optional<const Type *> getType(Type::ID id) const {
|
|
51
|
+
if (auto f = types.find(id); f != types.end())
|
|
52
|
+
return f->second.get();
|
|
53
|
+
return std::nullopt;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/// Register a type with the context. Takes ownership of the pointer type.
|
|
57
|
+
void registerType(Type *type);
|
|
58
|
+
|
|
59
|
+
/// Connect to an accelerator backend. Retains ownership internally and
|
|
60
|
+
/// returns a non-owning pointer.
|
|
61
|
+
AcceleratorConnection *connect(std::string backend, std::string connection);
|
|
62
|
+
|
|
63
|
+
/// Register a logger with the accelerator. Assumes ownership of the logger.
|
|
64
|
+
void setLogger(std::unique_ptr<Logger> logger) {
|
|
65
|
+
if (!logger)
|
|
66
|
+
throw std::invalid_argument("logger must not be null");
|
|
67
|
+
this->logger = std::move(logger);
|
|
68
|
+
}
|
|
69
|
+
inline Logger &getLogger() { return *logger; }
|
|
70
|
+
|
|
71
|
+
private:
|
|
72
|
+
std::unique_ptr<Logger> logger;
|
|
73
|
+
std::vector<std::unique_ptr<AcceleratorConnection>> connections;
|
|
74
|
+
|
|
75
|
+
private:
|
|
76
|
+
using TypeCache = std::map<Type::ID, std::unique_ptr<Type>>;
|
|
77
|
+
TypeCache types;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
} // namespace esi
|
|
81
|
+
|
|
82
|
+
#endif // ESI_CONTEXT_H
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
//===- Design.h - Dynamic accelerator 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 dynamic API into an accelerator allows access to the accelerator's design
|
|
10
|
+
// and communication channels through various stl containers (e.g. std::vector,
|
|
11
|
+
// std::map, etc.). This allows runtime reflection against the accelerator and
|
|
12
|
+
// can be pybind'd to create a Python API.
|
|
13
|
+
//
|
|
14
|
+
// The static API, in contrast, is a compile-time API that allows access to the
|
|
15
|
+
// design and communication channels symbolically. It will be generated once
|
|
16
|
+
// (not here) then compiled into the host software.
|
|
17
|
+
//
|
|
18
|
+
// Note for hardware designers: the "design hierarchy" from the host API
|
|
19
|
+
// perspective is not the same as the hardware module instance hierarchy.
|
|
20
|
+
// Rather, it is only the relevant parts as defined by the AppID hierarchy --
|
|
21
|
+
// levels in the hardware module instance hierarchy get skipped.
|
|
22
|
+
//
|
|
23
|
+
// DO NOT EDIT!
|
|
24
|
+
// This file is distributed as part of an ESI package. The source for this file
|
|
25
|
+
// should always be modified within CIRCT.
|
|
26
|
+
//
|
|
27
|
+
//===----------------------------------------------------------------------===//
|
|
28
|
+
|
|
29
|
+
// NOLINTNEXTLINE(llvm-header-guard)
|
|
30
|
+
#ifndef ESI_DESIGN_H
|
|
31
|
+
#define ESI_DESIGN_H
|
|
32
|
+
|
|
33
|
+
#include "esi/Manifest.h"
|
|
34
|
+
#include "esi/Ports.h"
|
|
35
|
+
#include "esi/Services.h"
|
|
36
|
+
|
|
37
|
+
#include <string>
|
|
38
|
+
|
|
39
|
+
namespace esi {
|
|
40
|
+
// Forward declarations.
|
|
41
|
+
class Instance;
|
|
42
|
+
namespace services {
|
|
43
|
+
class Service;
|
|
44
|
+
} // namespace services
|
|
45
|
+
|
|
46
|
+
/// Represents either the top level or an instance of a hardware module.
|
|
47
|
+
class HWModule {
|
|
48
|
+
public:
|
|
49
|
+
HWModule(const HWModule &) = delete;
|
|
50
|
+
HWModule &operator=(const HWModule &) = delete;
|
|
51
|
+
|
|
52
|
+
protected:
|
|
53
|
+
HWModule(std::optional<ModuleInfo> info,
|
|
54
|
+
std::vector<std::unique_ptr<Instance>> children,
|
|
55
|
+
std::vector<services::Service *> services,
|
|
56
|
+
std::vector<std::unique_ptr<BundlePort>> &&ports);
|
|
57
|
+
|
|
58
|
+
public:
|
|
59
|
+
virtual ~HWModule() = default;
|
|
60
|
+
|
|
61
|
+
/// Access the module's metadata, if any.
|
|
62
|
+
std::optional<ModuleInfo> getInfo() const { return info; }
|
|
63
|
+
/// Get a vector of the module's children in a deterministic order.
|
|
64
|
+
std::vector<const Instance *> getChildrenOrdered() const {
|
|
65
|
+
std::vector<const Instance *> ret;
|
|
66
|
+
for (const auto &c : children)
|
|
67
|
+
ret.push_back(c.get());
|
|
68
|
+
return ret;
|
|
69
|
+
}
|
|
70
|
+
/// Access the module's children by ID.
|
|
71
|
+
const std::map<AppID, Instance *> &getChildren() const { return childIndex; }
|
|
72
|
+
/// Get the module's ports in a deterministic order.
|
|
73
|
+
std::vector<std::reference_wrapper<BundlePort>> getPortsOrdered() const {
|
|
74
|
+
std::vector<std::reference_wrapper<BundlePort>> ret;
|
|
75
|
+
for (const auto &p : ports)
|
|
76
|
+
ret.push_back(*p);
|
|
77
|
+
return ret;
|
|
78
|
+
}
|
|
79
|
+
/// Access the module's ports by ID.
|
|
80
|
+
const std::map<AppID, BundlePort &> &getPorts() const { return portIndex; }
|
|
81
|
+
/// Access the services provided by this module.
|
|
82
|
+
const std::vector<services::Service *> &getServices() const {
|
|
83
|
+
return services;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/// Master poll method. Calls the `poll` method on all locally owned ports and
|
|
87
|
+
/// the master `poll` method on all of the children. Returns true if any of
|
|
88
|
+
/// the `poll` calls returns true.
|
|
89
|
+
bool poll();
|
|
90
|
+
|
|
91
|
+
/// Attempt to resolve a path to a module instance. If a child is not found,
|
|
92
|
+
/// return null and set lastLookup to the path which wasn't found.
|
|
93
|
+
const HWModule *resolveInst(const AppIDPath &path,
|
|
94
|
+
AppIDPath &lastLookup) const;
|
|
95
|
+
|
|
96
|
+
/// Attempt to resolve a path to a port. If a child or port is not found,
|
|
97
|
+
/// return null and set lastLookup to the path which wasn't found.
|
|
98
|
+
BundlePort *resolvePort(const AppIDPath &path, AppIDPath &lastLookup) const;
|
|
99
|
+
|
|
100
|
+
protected:
|
|
101
|
+
const std::optional<ModuleInfo> info;
|
|
102
|
+
const std::vector<std::unique_ptr<Instance>> children;
|
|
103
|
+
const std::map<AppID, Instance *> childIndex;
|
|
104
|
+
const std::vector<services::Service *> services;
|
|
105
|
+
const std::vector<std::unique_ptr<BundlePort>> ports;
|
|
106
|
+
const std::map<AppID, BundlePort &> portIndex;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
/// Subclass of `HWModule` which represents a submodule instance. Adds an AppID,
|
|
110
|
+
/// which the top level doesn't have or need.
|
|
111
|
+
class Instance : public HWModule {
|
|
112
|
+
public:
|
|
113
|
+
Instance() = delete;
|
|
114
|
+
Instance(const Instance &) = delete;
|
|
115
|
+
~Instance() = default;
|
|
116
|
+
Instance(AppID id, std::optional<ModuleInfo> info,
|
|
117
|
+
std::vector<std::unique_ptr<Instance>> children,
|
|
118
|
+
std::vector<services::Service *> services,
|
|
119
|
+
std::vector<std::unique_ptr<BundlePort>> &&ports)
|
|
120
|
+
: HWModule(info, std::move(children), services, std::move(ports)),
|
|
121
|
+
id(id) {}
|
|
122
|
+
|
|
123
|
+
/// Get the instance's ID, which it will always have.
|
|
124
|
+
AppID getID() const { return id; }
|
|
125
|
+
|
|
126
|
+
protected:
|
|
127
|
+
const AppID id;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
} // namespace esi
|
|
131
|
+
|
|
132
|
+
#endif // ESI_DESIGN_H
|