CIRCT 22.0.0git
Loading...
Searching...
No Matches
Accelerator.h
Go to the documentation of this file.
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
37namespace esi {
38// Forward declarations.
39class AcceleratorServiceThread;
40
41//===----------------------------------------------------------------------===//
42// Metadata constants which may or may not be used by various backends. Provided
43// here since they are intended to be somewhat standard.
44//===----------------------------------------------------------------------===//
45
46constexpr uint32_t MetadataOffset = 8;
47
48constexpr uint64_t MagicNumberLo = 0xE5100E51;
49constexpr uint64_t MagicNumberHi = 0x207D98E5;
50constexpr uint64_t MagicNumber = MagicNumberLo | (MagicNumberHi << 32);
51constexpr uint64_t MagicNumberOffset = 0;
52
53constexpr uint32_t ExpectedVersionNumber = 0;
54constexpr uint64_t VersionNumberOffset = 8;
55
56constexpr uint32_t ManifestPtrOffset = 0x10;
57
58constexpr uint32_t CycleCountOffset = 0x20;
59constexpr uint32_t CoreFreqOffset = 0x28;
60
61//===----------------------------------------------------------------------===//
62// Accelerator design hierarchy root.
63//===----------------------------------------------------------------------===//
64
65/// Top level accelerator class. Maintains a shared pointer to the manifest,
66/// which owns objects used in the design hierarchy owned by this class. Since
67/// this class owns the entire design hierarchy, when it gets destroyed the
68/// entire design hierarchy gets destroyed so all of the instances, ports, etc.
69/// are no longer valid pointers.
70class Accelerator : public HWModule {
71public:
72 Accelerator() = delete;
73 Accelerator(const Accelerator &) = delete;
74 ~Accelerator() = default;
75 Accelerator(std::optional<ModuleInfo> info,
76 std::vector<std::unique_ptr<Instance>> children,
77 std::vector<services::Service *> services,
78 std::vector<std::unique_ptr<BundlePort>> &&ports)
79 : HWModule(info, std::move(children), services, std::move(ports)) {}
80};
81
82//===----------------------------------------------------------------------===//
83// Connection to the accelerator and its services.
84//===----------------------------------------------------------------------===//
85
86/// Abstract class representing a connection to an accelerator. Actual
87/// connections (e.g. to a co-simulation or actual device) are implemented by
88/// subclasses. No methods in here are thread safe.
90public:
92 virtual ~AcceleratorConnection();
93 Context &getCtxt() const { return ctxt; }
94 Logger &getLogger() const { return ctxt.getLogger(); }
95
96 /// Disconnect from the accelerator cleanly.
97 virtual void disconnect();
98
99 /// Return a pointer to the accelerator 'service' thread (or threads). If the
100 /// thread(s) are not running, they will be started when this method is
101 /// called. `std::thread` is used. If users don't want the runtime to spin up
102 /// threads, don't call this method. `AcceleratorServiceThread` is owned by
103 /// AcceleratorConnection and governed by the lifetime of the this object.
105
107 /// Get a typed reference to a particular service type. Caller does *not* take
108 /// ownership of the returned pointer -- the Accelerator object owns it.
109 /// Pointer lifetime ends with the Accelerator lifetime.
110 template <typename ServiceClass>
111 ServiceClass *getService(AppIDPath id = {}, std::string implName = {},
112 ServiceImplDetails details = {},
113 HWClientDetails clients = {}) {
114 return dynamic_cast<ServiceClass *>(
115 getService(typeid(ServiceClass), id, implName, details, clients));
116 }
117 /// Calls `createService` and caches the result. Subclasses can override if
118 /// they want to use their own caching mechanism.
119 virtual Service *getService(Service::Type service, AppIDPath id = {},
120 std::string implName = {},
121 ServiceImplDetails details = {},
122 HWClientDetails clients = {});
123
124 /// Assume ownership of an accelerator object. Ties the lifetime of the
125 /// accelerator to this connection. Returns a raw pointer to the object.
126 Accelerator *takeOwnership(std::unique_ptr<Accelerator> accel);
127
128 /// Create a new engine for channel communication with the accelerator. The
129 /// default is to call the global `createEngine` to get an engine which has
130 /// registered itself. Individual accelerator connection backends can override
131 /// this to customize behavior.
132 virtual void createEngine(const std::string &engineTypeName, AppIDPath idPath,
133 const ServiceImplDetails &details,
134 const HWClientDetails &clients);
136 return clientEngines[id];
137 }
138
140 if (!ownedAccelerator)
141 throw std::runtime_error(
142 "AcceleratorConnection does not own an accelerator");
143 return *ownedAccelerator;
144 }
145
146protected:
147 /// If `createEngine` is overridden, this method should be called to register
148 /// the engine and all of the channels it services.
149 void registerEngine(AppIDPath idPath, std::unique_ptr<Engine> engine,
150 const HWClientDetails &clients);
151
152 /// Called by `getServiceImpl` exclusively. It wraps the pointer returned by
153 /// this in a unique_ptr and caches it. Separate this from the
154 /// wrapping/caching since wrapping/caching is an implementation detail.
156 std::string implName,
157 const ServiceImplDetails &details,
158 const HWClientDetails &clients) = 0;
159
160 /// Collection of owned engines.
161 std::map<AppIDPath, std::unique_ptr<Engine>> ownedEngines;
162 /// Mapping of clients to their servicing engines.
163 std::map<AppIDPath, BundleEngineMap> clientEngines;
164
165private:
166 /// ESI accelerator context.
168
169 /// Cache services via a unique_ptr so they get free'd automatically when
170 /// Accelerator objects get deconstructed.
171 using ServiceCacheKey = std::tuple<std::string, AppIDPath>;
172 std::map<ServiceCacheKey, std::unique_ptr<Service>> serviceCache;
173
174 std::unique_ptr<AcceleratorServiceThread> serviceThread;
175
176 /// Accelerator object owned by this connection.
177 std::unique_ptr<Accelerator> ownedAccelerator;
178};
179
180namespace registry {
181
182namespace internal {
183
184/// Backends can register themselves to be connected via a connection string.
185using BackendCreate = std::function<std::unique_ptr<AcceleratorConnection>(
186 Context &, std::string)>;
187void registerBackend(const std::string &name, BackendCreate create);
188
189// Helper struct to
190template <typename TAccelerator>
192 RegisterAccelerator(const char *name) {
193 registerBackend(name, &TAccelerator::connect);
194 }
195};
196
197#define REGISTER_ACCELERATOR(Name, TAccelerator) \
198 static ::esi::registry::internal::RegisterAccelerator<TAccelerator> \
199 __register_accel____LINE__(Name)
200
201} // namespace internal
202} // namespace registry
203
204/// Background thread which services various requests. Currently, it listens on
205/// ports and calls callbacks for incoming messages on said ports.
207public:
210
211 /// When there's data on any of the listenPorts, call the callback. Callable
212 /// from any thread.
213 void
214 addListener(std::initializer_list<ReadChannelPort *> listenPorts,
215 std::function<void(ReadChannelPort *, MessageData)> callback);
216
217 /// Poll this module.
218 void addPoll(HWModule &module);
219
220 /// Instruct the service thread to stop running.
221 void stop();
222
223private:
224 struct Impl;
225 std::unique_ptr<Impl> impl;
226};
227} // namespace esi
228
229#endif // ESI_ACCELERATOR_H
Abstract class representing a connection to an accelerator.
Definition Accelerator.h:89
std::tuple< std::string, AppIDPath > ServiceCacheKey
Cache services via a unique_ptr so they get free'd automatically when Accelerator objects get deconst...
virtual Service * createService(Service::Type service, AppIDPath idPath, std::string implName, const ServiceImplDetails &details, const HWClientDetails &clients)=0
Called by getServiceImpl exclusively.
services::Service Service
ServiceClass * getService(AppIDPath id={}, std::string implName={}, ServiceImplDetails details={}, HWClientDetails clients={})
Get a typed reference to a particular service type.
Context & getCtxt() const
Definition Accelerator.h:93
std::map< AppIDPath, BundleEngineMap > clientEngines
Mapping of clients to their servicing engines.
Context & ctxt
ESI accelerator context.
void registerEngine(AppIDPath idPath, std::unique_ptr< Engine > engine, const HWClientDetails &clients)
If createEngine is overridden, this method should be called to register the engine and all of the cha...
std::map< ServiceCacheKey, std::unique_ptr< Service > > serviceCache
std::unique_ptr< AcceleratorServiceThread > serviceThread
std::unique_ptr< Accelerator > ownedAccelerator
Accelerator object owned by this connection.
virtual void disconnect()
Disconnect from the accelerator cleanly.
std::map< AppIDPath, std::unique_ptr< Engine > > ownedEngines
Collection of owned engines.
Accelerator & getAccelerator()
virtual void createEngine(const std::string &engineTypeName, AppIDPath idPath, const ServiceImplDetails &details, const HWClientDetails &clients)
Create a new engine for channel communication with the accelerator.
virtual const BundleEngineMap & getEngineMapFor(AppIDPath id)
Logger & getLogger() const
Definition Accelerator.h:94
AcceleratorServiceThread * getServiceThread()
Return a pointer to the accelerator 'service' thread (or threads).
Accelerator * takeOwnership(std::unique_ptr< Accelerator > accel)
Assume ownership of an accelerator object.
Background thread which services various requests.
std::unique_ptr< Impl > impl
void stop()
Instruct the service thread to stop running.
void addPoll(HWModule &module)
Poll this module.
void addListener(std::initializer_list< ReadChannelPort * > listenPorts, std::function< void(ReadChannelPort *, MessageData)> callback)
When there's data on any of the listenPorts, call the callback.
Top level accelerator class.
Definition Accelerator.h:70
Accelerator(std::optional< ModuleInfo > info, std::vector< std::unique_ptr< Instance > > children, std::vector< services::Service * > services, std::vector< std::unique_ptr< BundlePort > > &&ports)
Definition Accelerator.h:75
~Accelerator()=default
Accelerator()=delete
Accelerator(const Accelerator &)=delete
Since engines can support multiple channels BUT not necessarily all of the channels in a bundle,...
Definition Engines.h:73
AcceleratorConnections, Accelerators, and Manifests must all share a context.
Definition Context.h:34
Logger & getLogger()
Definition Context.h:69
Represents either the top level or an instance of a hardware module.
Definition Design.h:47
const std::optional< ModuleInfo > info
Definition Design.h:101
const std::vector< std::unique_ptr< BundlePort > > ports
Definition Design.h:105
const std::vector< std::unique_ptr< Instance > > children
Definition Design.h:102
const std::vector< services::Service * > services
Definition Design.h:104
A logical chunk of data representing serialized data.
Definition Common.h:113
A ChannelPort which reads data from the accelerator.
Definition Ports.h:318
Parent class of all APIs modeled as 'services'.
Definition Services.h:59
const std::type_info & Type
Definition Services.h:61
void registerBackend(const std::string &name, BackendCreate create)
std::function< std::unique_ptr< AcceleratorConnection >(Context &, std::string)> BackendCreate
Backends can register themselves to be connected via a connection string.
Definition esi.py:1
constexpr uint32_t CoreFreqOffset
Definition Accelerator.h:59
constexpr uint64_t MagicNumber
Definition Accelerator.h:50
std::map< std::string, std::any > ServiceImplDetails
Definition Common.h:108
constexpr uint64_t MagicNumberHi
Definition Accelerator.h:49
constexpr uint32_t ExpectedVersionNumber
Definition Accelerator.h:53
constexpr uint64_t MagicNumberOffset
Definition Accelerator.h:51
constexpr uint32_t MetadataOffset
Definition Accelerator.h:46
constexpr uint32_t CycleCountOffset
Definition Accelerator.h:58
constexpr uint32_t ManifestPtrOffset
Definition Accelerator.h:56
constexpr uint64_t MagicNumberLo
Definition Accelerator.h:48
constexpr uint64_t VersionNumberOffset
Definition Accelerator.h:54
std::vector< HWClientDetail > HWClientDetails
Definition Common.h:107