CIRCT 20.0.0git
Loading...
Searching...
No Matches
Ports.h
Go to the documentation of this file.
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
26namespace esi {
27
28/// Unidirectional channels are the basic communication primitive between the
29/// host and accelerator. A 'ChannelPort' is the host side of a channel. It can
30/// be either read or write but not both. At this level, channels are untyped --
31/// just streams of bytes. They are not intended to be used directly by users
32/// but used by higher level APIs which add types.
34public:
36 virtual ~ChannelPort() {}
37
38 /// Set up a connection to the accelerator. The buffer size is optional and
39 /// should be considered merely a hint. Individual implementations use it
40 /// however they like. The unit is number of messages of the port type.
41 virtual void connect(std::optional<unsigned> bufferSize = std::nullopt) = 0;
42 virtual void disconnect() = 0;
43 virtual bool isConnected() const = 0;
44
45 /// Poll for incoming data. Returns true if data was read or written into a
46 /// buffer as a result of the poll. Calling the call back could (will) also
47 /// happen in that case. Some backends need this to be called periodically. In
48 /// the usual case, this will be called by a background thread, but the ESI
49 /// runtime does not want to assume that the host processes use standard
50 /// threads. If the user wants to provide their own threads, they need to call
51 /// this on each port occasionally. This is also called from the 'master' poll
52 /// method in the Accelerator class.
53 bool poll() {
54 if (isConnected())
55 return pollImpl();
56 return false;
57 }
58
59 const Type *getType() const { return type; }
60
61protected:
62 const Type *type;
63
64 /// Method called by poll() to actually poll the channel if the channel is
65 /// connected.
66 virtual bool pollImpl() { return false; }
67
68 /// Called by all connect methods to let backends initiate the underlying
69 /// connections.
70 virtual void connectImpl(std::optional<unsigned> bufferSize) {}
71};
72
73/// A ChannelPort which sends data to the accelerator.
75public:
77
78 virtual void
79 connect(std::optional<unsigned> bufferSize = std::nullopt) override {
80 connectImpl(bufferSize);
81 connected = true;
82 }
83 virtual void disconnect() override { connected = false; }
84 virtual bool isConnected() const override { return connected; }
85
86 /// A very basic blocking write API. Will likely change for performance
87 /// reasons.
88 virtual void write(const MessageData &) = 0;
89
90 /// A basic non-blocking write API. Returns true if the data was written.
91 /// It is invalid for backends to always return false (i.e. backends must
92 /// eventually ensure that writes may succeed).
93 virtual bool tryWrite(const MessageData &data) = 0;
94
95private:
96 volatile bool connected = false;
97};
98
99/// A ChannelPort which reads data from the accelerator. It has two modes:
100/// Callback and Polling which cannot be used at the same time. The mode is set
101/// at connect() time. To change the mode, disconnect() and then connect()
102/// again.
104
105public:
108 virtual void disconnect() override { mode = Mode::Disconnected; }
109 virtual bool isConnected() const override {
110 return mode != Mode::Disconnected;
111 }
112
113 //===--------------------------------------------------------------------===//
114 // Callback mode: To use a callback, connect with a callback function which
115 // will get called with incoming data. This function can be called from any
116 // thread. It shall return true to indicate that the data was consumed. False
117 // if it could not accept the data and should be tried again at some point in
118 // the future. Callback is not allowed to block and needs to execute quickly.
119 //
120 // TODO: Have the callback return something upon which the caller can check,
121 // wait, and be notified.
122 //===--------------------------------------------------------------------===//
123
124 virtual void connect(std::function<bool(MessageData)> callback,
125 std::optional<unsigned> bufferSize = std::nullopt);
126
127 //===--------------------------------------------------------------------===//
128 // Polling mode methods: To use futures or blocking reads, connect without any
129 // arguments. You will then be able to use readAsync() or read().
130 //===--------------------------------------------------------------------===//
131
132 /// Default max data queue size set at connect time.
133 static constexpr uint64_t DefaultMaxDataQueueMsgs = 32;
134
135 /// Connect to the channel in polling mode.
136 virtual void
137 connect(std::optional<unsigned> bufferSize = std::nullopt) override;
138
139 /// Asynchronous read.
140 virtual std::future<MessageData> readAsync();
141
142 /// Specify a buffer to read into. Blocking. Basic API, will likely change
143 /// for performance and functionality reasons.
144 virtual void read(MessageData &outData) {
145 std::future<MessageData> f = readAsync();
146 f.wait();
147 outData = std::move(f.get());
148 }
149
150 /// Set maximum number of messages to store in the dataQueue. 0 means no
151 /// limit. This is only used in polling mode and is set to default of 32 upon
152 /// connect. While it may seem redundant to have this and bufferSize, there
153 /// may be (and are) backends which have a very small amount of memory which
154 /// are accelerator accessible and want to move messages out as quickly as
155 /// possible.
156 void setMaxDataQueueMsgs(uint64_t maxMsgs) { maxDataQueueMsgs = maxMsgs; }
157
158protected:
159 /// Indicates the current mode of the channel.
161 volatile Mode mode;
162
163 /// Backends call this callback when new data is available.
164 std::function<bool(MessageData)> callback;
165
166 //===--------------------------------------------------------------------===//
167 // Polling mode members.
168 //===--------------------------------------------------------------------===//
169
170 /// Mutex to protect the two queues used for polling.
171 std::mutex pollingM;
172 /// Store incoming data here if there are no outstanding promises to be
173 /// fulfilled.
174 std::queue<MessageData> dataQueue;
175 /// Maximum number of messages to store in dataQueue. 0 means no limit.
177 /// Promises to be fulfilled when data is available.
178 std::queue<std::promise<MessageData>> promiseQueue;
179};
180
181/// Services provide connections to 'bundles' -- collections of named,
182/// unidirectional communication channels. This class provides access to those
183/// ChannelPorts.
185public:
186 /// Compute the direction of a channel given the bundle direction and the
187 /// bundle port's direction.
188 static bool isWrite(BundleType::Direction bundleDir) {
189 return bundleDir == BundleType::Direction::To;
190 }
191
192 /// Construct a port.
193 BundlePort(AppID id, std::map<std::string, ChannelPort &> channels);
194 virtual ~BundlePort() = default;
195
196 /// Get the ID of the port.
197 AppID getID() const { return id; }
198
199 /// Get access to the raw byte streams of a channel. Intended for internal
200 /// usage and binding to other languages (e.g. Python) which have their own
201 /// message serialization code. Exposed publicly as an escape hatch, but
202 /// ordinary users should not use. You have been warned.
203 WriteChannelPort &getRawWrite(const std::string &name) const;
204 ReadChannelPort &getRawRead(const std::string &name) const;
205 const std::map<std::string, ChannelPort &> &getChannels() const {
206 return channels;
207 }
208
209 /// Cast this Bundle port to a subclass which is actually useful. Returns
210 /// nullptr if the cast fails.
211 // TODO: this probably shouldn't be 'const', but bundle ports' user access are
212 // const. Change that.
213 template <typename T>
214 T *getAs() const {
215 return const_cast<T *>(dynamic_cast<const T *>(this));
216 }
217
218 /// Calls `poll` on all channels in the bundle and returns true if any of them
219 /// returned true.
220 bool poll() {
221 bool result = false;
222 for (auto &channel : channels)
223 result |= channel.second.poll();
224 return result;
225 }
226
227private:
229 std::map<std::string, ChannelPort &> channels;
230};
231
232} // namespace esi
233
234#endif // ESI_PORTS_H
Services provide connections to 'bundles' – collections of named, unidirectional communication channe...
Definition Ports.h:184
virtual ~BundlePort()=default
std::map< std::string, ChannelPort & > channels
Definition Ports.h:229
T * getAs() const
Cast this Bundle port to a subclass which is actually useful.
Definition Ports.h:214
ReadChannelPort & getRawRead(const std::string &name) const
Definition Ports.cpp:35
WriteChannelPort & getRawWrite(const std::string &name) const
Get access to the raw byte streams of a channel.
Definition Ports.cpp:25
bool poll()
Calls poll on all channels in the bundle and returns true if any of them returned true.
Definition Ports.h:220
static bool isWrite(BundleType::Direction bundleDir)
Compute the direction of a channel given the bundle direction and the bundle port's direction.
Definition Ports.h:188
const std::map< std::string, ChannelPort & > & getChannels() const
Definition Ports.h:205
AppID getID() const
Get the ID of the port.
Definition Ports.h:197
Unidirectional channels are the basic communication primitive between the host and accelerator.
Definition Ports.h:33
const Type * getType() const
Definition Ports.h:59
ChannelPort(const Type *type)
Definition Ports.h:35
virtual void disconnect()=0
virtual void connect(std::optional< unsigned > bufferSize=std::nullopt)=0
Set up a connection to the accelerator.
virtual void connectImpl(std::optional< unsigned > bufferSize)
Called by all connect methods to let backends initiate the underlying connections.
Definition Ports.h:70
virtual bool pollImpl()
Method called by poll() to actually poll the channel if the channel is connected.
Definition Ports.h:66
const Type * type
Definition Ports.h:62
virtual ~ChannelPort()
Definition Ports.h:36
bool poll()
Poll for incoming data.
Definition Ports.h:53
virtual bool isConnected() const =0
A logical chunk of data representing serialized data.
Definition Common.h:103
A ChannelPort which reads data from the accelerator.
Definition Ports.h:103
volatile Mode mode
Definition Ports.h:161
virtual std::future< MessageData > readAsync()
Asynchronous read.
Definition Ports.cpp:77
virtual bool isConnected() const override
Definition Ports.h:109
std::mutex pollingM
Mutex to protect the two queues used for polling.
Definition Ports.h:171
virtual void connect(std::function< bool(MessageData)> callback, std::optional< unsigned > bufferSize=std::nullopt)
Definition Ports.cpp:44
std::function< bool(MessageData)> callback
Backends call this callback when new data is available.
Definition Ports.h:164
Mode
Indicates the current mode of the channel.
Definition Ports.h:160
std::queue< MessageData > dataQueue
Store incoming data here if there are no outstanding promises to be fulfilled.
Definition Ports.h:174
static constexpr uint64_t DefaultMaxDataQueueMsgs
Default max data queue size set at connect time.
Definition Ports.h:133
std::queue< std::promise< MessageData > > promiseQueue
Promises to be fulfilled when data is available.
Definition Ports.h:178
void setMaxDataQueueMsgs(uint64_t maxMsgs)
Set maximum number of messages to store in the dataQueue.
Definition Ports.h:156
uint64_t maxDataQueueMsgs
Maximum number of messages to store in dataQueue. 0 means no limit.
Definition Ports.h:176
virtual void disconnect() override
Definition Ports.h:108
virtual void read(MessageData &outData)
Specify a buffer to read into.
Definition Ports.h:144
ReadChannelPort(const Type *type)
Definition Ports.h:106
Root class of the ESI type system.
Definition Types.h:27
A ChannelPort which sends data to the accelerator.
Definition Ports.h:74
virtual bool isConnected() const override
Definition Ports.h:84
virtual void disconnect() override
Definition Ports.h:83
volatile bool connected
Definition Ports.h:96
virtual void write(const MessageData &)=0
A very basic blocking write API.
virtual bool tryWrite(const MessageData &data)=0
A basic non-blocking write API.
virtual void connect(std::optional< unsigned > bufferSize=std::nullopt) override
Set up a connection to the accelerator.
Definition Ports.h:79
Definition esi.py:1