CIRCT  19.0.0git
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/Manifest.h"
27 #include "esi/Ports.h"
28 #include "esi/Services.h"
29 
30 #include <functional>
31 #include <map>
32 #include <memory>
33 #include <string>
34 #include <typeinfo>
35 
36 namespace esi {
37 // Forward declarations.
38 class AcceleratorServiceThread;
39 
40 //===----------------------------------------------------------------------===//
41 // Constants used by low-level APIs.
42 //===----------------------------------------------------------------------===//
43 
44 constexpr uint32_t MetadataOffset = 8;
45 constexpr uint64_t MagicNumberLo = 0xE5100E51;
46 constexpr uint64_t MagicNumberHi = 0x207D98E5;
47 constexpr uint64_t MagicNumber = MagicNumberLo | (MagicNumberHi << 32);
48 constexpr uint32_t ExpectedVersionNumber = 0;
49 
50 //===----------------------------------------------------------------------===//
51 // Accelerator design hierarchy root.
52 //===----------------------------------------------------------------------===//
53 
54 /// Top level accelerator class. Maintains a shared pointer to the manifest,
55 /// which owns objects used in the design hierarchy owned by this class. Since
56 /// this class owns the entire design hierarchy, when it gets destroyed the
57 /// entire design hierarchy gets destroyed so all of the instances, ports, etc.
58 /// are no longer valid pointers.
59 class Accelerator : public HWModule {
60 public:
61  Accelerator() = delete;
62  Accelerator(const Accelerator &) = delete;
63  ~Accelerator() = default;
64  Accelerator(std::optional<ModuleInfo> info,
65  std::vector<std::unique_ptr<Instance>> children,
66  std::vector<services::Service *> services,
67  std::vector<std::unique_ptr<BundlePort>> &ports)
68  : HWModule(info, std::move(children), services, ports) {}
69 };
70 
71 //===----------------------------------------------------------------------===//
72 // Connection to the accelerator and its services.
73 //===----------------------------------------------------------------------===//
74 
75 /// Abstract class representing a connection to an accelerator. Actual
76 /// connections (e.g. to a co-simulation or actual device) are implemented by
77 /// subclasses.
79 public:
81  virtual ~AcceleratorConnection() = default;
82  Context &getCtxt() const { return ctxt; }
83 
84  /// Disconnect from the accelerator cleanly.
85  void disconnect();
86 
87  /// Request the host side channel ports for a particular instance (identified
88  /// by the AppID path). For convenience, provide the bundle type.
89  virtual std::map<std::string, ChannelPort &>
91 
93 
95  /// Get a typed reference to a particular service type. Caller does *not* take
96  /// ownership of the returned pointer -- the Accelerator object owns it.
97  /// Pointer lifetime ends with the Accelerator lifetime.
98  template <typename ServiceClass>
99  ServiceClass *getService(AppIDPath id = {}, std::string implName = {},
100  ServiceImplDetails details = {},
101  HWClientDetails clients = {}) {
102  return dynamic_cast<ServiceClass *>(
103  getService(typeid(ServiceClass), id, implName, details, clients));
104  }
105  /// Calls `createService` and caches the result. Subclasses can override if
106  /// they want to use their own caching mechanism.
107  virtual Service *getService(Service::Type service, AppIDPath id = {},
108  std::string implName = {},
109  ServiceImplDetails details = {},
110  HWClientDetails clients = {});
111 
112 protected:
113  /// Called by `getServiceImpl` exclusively. It wraps the pointer returned by
114  /// this in a unique_ptr and caches it. Separate this from the
115  /// wrapping/caching since wrapping/caching is an implementation detail.
116  virtual Service *createService(Service::Type service, AppIDPath idPath,
117  std::string implName,
118  const ServiceImplDetails &details,
119  const HWClientDetails &clients) = 0;
120 
121 private:
122  /// ESI accelerator context.
124 
125  /// Cache services via a unique_ptr so they get free'd automatically when
126  /// Accelerator objects get deconstructed.
127  using ServiceCacheKey = std::tuple<const std::type_info *, AppIDPath>;
128  std::map<ServiceCacheKey, std::unique_ptr<Service>> serviceCache;
129 
130  std::unique_ptr<AcceleratorServiceThread> serviceThread;
131 };
132 
133 namespace registry {
134 
135 // Connect to an ESI accelerator given a backend name and connection specifier.
136 // Alternatively, instantiate the backend directly (if you're using C++).
137 std::unique_ptr<AcceleratorConnection>
138 connect(Context &ctxt, std::string backend, std::string connection);
139 
140 namespace internal {
141 
142 /// Backends can register themselves to be connected via a connection string.
143 using BackendCreate = std::function<std::unique_ptr<AcceleratorConnection>(
144  Context &, std::string)>;
145 void registerBackend(std::string name, BackendCreate create);
146 
147 // Helper struct to
148 template <typename TAccelerator>
150  RegisterAccelerator(const char *name) {
152  }
153 };
154 
155 #define REGISTER_ACCELERATOR(Name, TAccelerator) \
156  static ::esi::registry::internal::RegisterAccelerator<TAccelerator> \
157  __register_accel____LINE__(Name)
158 
159 } // namespace internal
160 } // namespace registry
161 
162 /// Background thread which services various requests. Currently, it listens on
163 /// ports and calls callbacks for incoming messages on said ports.
165 public:
168 
169  /// When there's data on any of the listenPorts, call the callback. Callable
170  /// from any thread.
171  void
172  addListener(std::initializer_list<ReadChannelPort *> listenPorts,
173  std::function<void(ReadChannelPort *, MessageData)> callback);
174 
175  /// Instruct the service thread to stop running.
176  void stop();
177 
178 private:
179  struct Impl;
180  std::unique_ptr<Impl> impl;
181 };
182 } // namespace esi
183 
184 #endif // ESI_ACCELERATOR_H
Abstract class representing a connection to an accelerator.
Definition: Accelerator.h:78
Context & getCtxt() const
Definition: Accelerator.h:82
void disconnect()
Disconnect from the accelerator cleanly.
services::Service Service
Definition: Accelerator.h:94
ServiceClass * getService(AppIDPath id={}, std::string implName={}, ServiceImplDetails details={}, HWClientDetails clients={})
Get a typed reference to a particular service type.
Definition: Accelerator.h:99
Context & ctxt
ESI accelerator context.
Definition: Accelerator.h:123
std::map< ServiceCacheKey, std::unique_ptr< Service > > serviceCache
Definition: Accelerator.h:128
std::tuple< const std::type_info *, AppIDPath > ServiceCacheKey
Cache services via a unique_ptr so they get free'd automatically when Accelerator objects get deconst...
Definition: Accelerator.h:127
std::unique_ptr< AcceleratorServiceThread > serviceThread
Definition: Accelerator.h:130
virtual Service * createService(Service::Type service, AppIDPath idPath, std::string implName, const ServiceImplDetails &details, const HWClientDetails &clients)=0
Called by getServiceImpl exclusively.
virtual std::map< std::string, ChannelPort & > requestChannelsFor(AppIDPath, const BundleType *)=0
Request the host side channel ports for a particular instance (identified by the AppID path).
AcceleratorConnection(Context &ctxt)
Definition: Accelerator.cpp:36
virtual ~AcceleratorConnection()=default
AcceleratorServiceThread * getServiceThread()
Definition: Accelerator.h:92
Background thread which services various requests.
Definition: Accelerator.h:164
void stop()
Instruct the service thread to stop running.
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.
std::unique_ptr< Impl > impl
Definition: Accelerator.h:179
Top level accelerator class.
Definition: Accelerator.h:59
~Accelerator()=default
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:64
Accelerator()=delete
Accelerator(const Accelerator &)=delete
Bundles represent a collection of channels.
Definition: Types.h:44
AcceleratorConnections, Accelerators, and Manifests must all share a context.
Definition: Context.h:30
Represents either the top level or an instance of a hardware module.
Definition: Design.h:47
const std::optional< ModuleInfo > info
Definition: Design.h:81
const std::vector< std::unique_ptr< BundlePort > > ports
Definition: Design.h:85
const std::vector< std::unique_ptr< Instance > > children
Definition: Design.h:82
const std::vector< services::Service * > services
Definition: Design.h:84
A logical chunk of data representing serialized data.
Definition: Common.h:86
A ChannelPort which reads data from the accelerator.
Definition: Ports.h:69
Parent class of all APIs modeled as 'services'.
Definition: Services.h:42
const std::type_info & Type
Definition: Services.h:44
void registerBackend(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: Accelerator.h:144
std::unique_ptr< AcceleratorConnection > connect(Context &ctxt, std::string backend, std::string connection)
Definition: esi.py:1
constexpr uint64_t MagicNumber
Definition: Accelerator.h:47
std::map< std::string, std::any > ServiceImplDetails
Definition: Common.h:81
constexpr uint64_t MagicNumberHi
Definition: Accelerator.h:46
constexpr uint32_t ExpectedVersionNumber
Definition: Accelerator.h:48
constexpr uint32_t MetadataOffset
Definition: Accelerator.h:44
constexpr uint64_t MagicNumberLo
Definition: Accelerator.h:45
std::vector< HWClientDetail > HWClientDetails
Definition: Common.h:80