esiaccel 0.2.3.dev49__cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.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/__init__.py +31 -0
- esiaccel/accelerator.py +134 -0
- esiaccel/bin/esi-cosim.py +104 -0
- esiaccel/bin/esiquery +0 -0
- esiaccel/cmake/esiaccelConfig.cmake +49 -0
- esiaccel/codegen.py +197 -0
- esiaccel/cosim/Cosim_CycleCount.sv +84 -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 +383 -0
- esiaccel/cosim/verilator.py +92 -0
- esiaccel/esiCppAccel.cpython-314-x86_64-linux-gnu.so +0 -0
- esiaccel/esiCppAccel.pyi +337 -0
- esiaccel/include/esi/Accelerator.h +229 -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 +467 -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/lib/libCosimBackend.so +0 -0
- esiaccel/lib/libCosimRpc.so +0 -0
- esiaccel/lib/libESICppRuntime.so +0 -0
- esiaccel/lib/libEsiCosimDpiServer.so +0 -0
- esiaccel/lib/libMtiPli.so +0 -0
- esiaccel/types.py +565 -0
- esiaccel/utils.py +54 -0
- esiaccel-0.2.3.dev49.dist-info/METADATA +254 -0
- esiaccel-0.2.3.dev49.dist-info/RECORD +47 -0
- esiaccel-0.2.3.dev49.dist-info/WHEEL +6 -0
- esiaccel-0.2.3.dev49.dist-info/entry_points.txt +4 -0
- esiaccel-0.2.3.dev49.dist-info/licenses/LICENSE +234 -0
- esiaccel-0.2.3.dev49.dist-info/top_level.txt +1 -0
|
@@ -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
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
//===- Engines.h - Implement port communication -----------------*- 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
|
+
// Engines (as in DMA engine) implement the actual communication between the
|
|
16
|
+
// host and the accelerator. They are low level of the ESI runtime API and are
|
|
17
|
+
// not intended to be used directly by users.
|
|
18
|
+
//
|
|
19
|
+
// They are called "engines" rather than "DMA engines" since communication need
|
|
20
|
+
// not be implemented via DMA.
|
|
21
|
+
//
|
|
22
|
+
//===----------------------------------------------------------------------===//
|
|
23
|
+
|
|
24
|
+
// NOLINTNEXTLINE(llvm-header-guard)
|
|
25
|
+
#ifndef ESI_ENGINGES_H
|
|
26
|
+
#define ESI_ENGINGES_H
|
|
27
|
+
|
|
28
|
+
#include "esi/Common.h"
|
|
29
|
+
#include "esi/Ports.h"
|
|
30
|
+
#include "esi/Services.h"
|
|
31
|
+
#include "esi/Utils.h"
|
|
32
|
+
|
|
33
|
+
#include <cassert>
|
|
34
|
+
#include <future>
|
|
35
|
+
|
|
36
|
+
namespace esi {
|
|
37
|
+
class Accelerator;
|
|
38
|
+
|
|
39
|
+
/// Engines implement the actual channel communication between the host and the
|
|
40
|
+
/// accelerator. Engines can support multiple channels. They are low level of
|
|
41
|
+
/// the ESI runtime API and are not intended to be used directly by users.
|
|
42
|
+
class Engine {
|
|
43
|
+
public:
|
|
44
|
+
Engine(AcceleratorConnection &conn) : connected(false), conn(conn) {}
|
|
45
|
+
virtual ~Engine() = default;
|
|
46
|
+
/// Start the engine, if applicable.
|
|
47
|
+
virtual void connect() { connected = true; };
|
|
48
|
+
/// Stop the engine, if applicable.
|
|
49
|
+
virtual void disconnect() { connected = false; };
|
|
50
|
+
/// Get a port for a channel, from the cache if it exists or create it. An
|
|
51
|
+
/// engine may override this method if different behavior is desired.
|
|
52
|
+
virtual ChannelPort &requestPort(AppIDPath idPath,
|
|
53
|
+
const std::string &channelName,
|
|
54
|
+
BundleType::Direction dir, const Type *type);
|
|
55
|
+
|
|
56
|
+
protected:
|
|
57
|
+
/// Each engine needs to know how to create a ports. This method is called if
|
|
58
|
+
/// a port doesn't exist in the engine cache.
|
|
59
|
+
virtual std::unique_ptr<ChannelPort>
|
|
60
|
+
createPort(AppIDPath idPath, const std::string &channelName,
|
|
61
|
+
BundleType::Direction dir, const Type *type) = 0;
|
|
62
|
+
|
|
63
|
+
bool connected;
|
|
64
|
+
AcceleratorConnection &conn;
|
|
65
|
+
|
|
66
|
+
private:
|
|
67
|
+
std::map<std::pair<AppIDPath, std::string>, std::unique_ptr<ChannelPort>>
|
|
68
|
+
ownedPorts;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/// Since engines can support multiple channels BUT not necessarily all of the
|
|
72
|
+
/// channels in a bundle, a mapping from bundle channels to engines is needed.
|
|
73
|
+
class BundleEngineMap {
|
|
74
|
+
friend class AcceleratorConnection;
|
|
75
|
+
|
|
76
|
+
public:
|
|
77
|
+
/// Request ports for all the channels in a bundle. If the engine doesn't
|
|
78
|
+
/// exist for a particular channel, skip said channel.
|
|
79
|
+
PortMap requestPorts(const AppIDPath &idPath,
|
|
80
|
+
const BundleType *bundleType) const;
|
|
81
|
+
|
|
82
|
+
private:
|
|
83
|
+
/// Set a particlar engine for a particular channel. Should only be called by
|
|
84
|
+
/// AcceleratorConnection while registering engines.
|
|
85
|
+
void setEngine(const std::string &channelName, Engine *engine);
|
|
86
|
+
std::map<std::string, Engine *> bundleEngineMap;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
namespace registry {
|
|
90
|
+
|
|
91
|
+
/// Create an engine by name. This is the primary way to create engines for
|
|
92
|
+
/// "normal" backends.
|
|
93
|
+
std::unique_ptr<Engine> createEngine(AcceleratorConnection &conn,
|
|
94
|
+
const std::string &dmaEngineName,
|
|
95
|
+
AppIDPath idPath,
|
|
96
|
+
const ServiceImplDetails &details,
|
|
97
|
+
const HWClientDetails &clients);
|
|
98
|
+
|
|
99
|
+
namespace internal {
|
|
100
|
+
|
|
101
|
+
/// Engines can register themselves for pluggable functionality.
|
|
102
|
+
using EngineCreate = std::function<std::unique_ptr<Engine>(
|
|
103
|
+
AcceleratorConnection &conn, AppIDPath idPath,
|
|
104
|
+
const ServiceImplDetails &details, const HWClientDetails &clients)>;
|
|
105
|
+
void registerEngine(const std::string &name, EngineCreate create);
|
|
106
|
+
|
|
107
|
+
/// Helper struct to register engines.
|
|
108
|
+
template <typename TEngine>
|
|
109
|
+
struct RegisterEngine {
|
|
110
|
+
RegisterEngine(const char *name) { registerEngine(name, &TEngine::create); }
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
#define CONCAT_(prefix, suffix) prefix##suffix
|
|
114
|
+
#define CONCAT(prefix, suffix) CONCAT_(prefix, suffix)
|
|
115
|
+
#define REGISTER_ENGINE(Name, TEngine) \
|
|
116
|
+
static ::esi::registry::internal::RegisterEngine<TEngine> CONCAT( \
|
|
117
|
+
__register_engine__, __LINE__)(Name)
|
|
118
|
+
|
|
119
|
+
} // namespace internal
|
|
120
|
+
} // namespace registry
|
|
121
|
+
|
|
122
|
+
} // namespace esi
|
|
123
|
+
|
|
124
|
+
#endif // ESI_PORTS_H
|