CIRCT  19.0.0git
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 
26 namespace 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.
33 class ChannelPort {
34 public:
35  ChannelPort(const Type *type) : type(type) {}
36  virtual ~ChannelPort() { disconnect(); }
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) {
42  connectImpl(bufferSize);
43  }
44  virtual void disconnect() {}
45 
46  const Type *getType() const { return type; }
47 
48 private:
49  const Type *type;
50 
51  /// Called by all connect methods to let backends initiate the underlying
52  /// connections.
53  virtual void connectImpl(std::optional<unsigned> bufferSize) {}
54 };
55 
56 /// A ChannelPort which sends data to the accelerator.
57 class WriteChannelPort : public ChannelPort {
58 public:
60 
61  /// A very basic write API. Will likely change for performance reasons.
62  virtual void write(const MessageData &) = 0;
63 };
64 
65 /// A ChannelPort which reads data from the accelerator. It has two modes:
66 /// Callback and Polling which cannot be used at the same time. The mode is set
67 /// at connect() time. To change the mode, disconnect() and then connect()
68 /// again.
69 class ReadChannelPort : public ChannelPort {
70 
71 public:
74  virtual void disconnect() override { mode = Mode::Disconnected; }
75 
76  //===--------------------------------------------------------------------===//
77  // Callback mode: To use a callback, connect with a callback function which
78  // will get called with incoming data. This function can be called from any
79  // thread. It shall return true to indicate that the data was consumed. False
80  // if it could not accept the data and should be tried again at some point in
81  // the future. Callback is not allowed to block and needs to execute quickly.
82  //
83  // TODO: Have the callback return something upon which the caller can check,
84  // wait, and be notified.
85  //===--------------------------------------------------------------------===//
86 
87  virtual void connect(std::function<bool(MessageData)> callback,
88  std::optional<unsigned> bufferSize = std::nullopt);
89 
90  //===--------------------------------------------------------------------===//
91  // Polling mode methods: To use futures or blocking reads, connect without any
92  // arguments. You will then be able to use readAsync() or read().
93  //===--------------------------------------------------------------------===//
94 
95  /// Default max data queue size set at connect time.
96  static constexpr uint64_t DefaultMaxDataQueueMsgs = 32;
97 
98  /// Connect to the channel in polling mode.
99  virtual void
100  connect(std::optional<unsigned> bufferSize = std::nullopt) override;
101 
102  /// Asynchronous read.
103  virtual std::future<MessageData> readAsync();
104 
105  /// Specify a buffer to read into. Blocking. Basic API, will likely change
106  /// for performance and functionality reasons.
107  virtual void read(MessageData &outData) {
108  std::future<MessageData> f = readAsync();
109  f.wait();
110  outData = std::move(f.get());
111  }
112 
113  /// Set maximum number of messages to store in the dataQueue. 0 means no
114  /// limit. This is only used in polling mode and is set to default of 32 upon
115  /// connect. While it may seem redundant to have this and bufferSize, there
116  /// may be (and are) backends which have a very small amount of memory which
117  /// are accelerator accessible and want to move messages out as quickly as
118  /// possible.
119  void setMaxDataQueueMsgs(uint64_t maxMsgs) { maxDataQueueMsgs = maxMsgs; }
120 
121 protected:
122  /// Indicates the current mode of the channel.
125 
126  /// Backends call this callback when new data is available.
127  std::function<bool(MessageData)> callback;
128 
129  //===--------------------------------------------------------------------===//
130  // Polling mode members.
131  //===--------------------------------------------------------------------===//
132 
133  /// Mutex to protect the two queues used for polling.
134  std::mutex pollingM;
135  /// Store incoming data here if there are no outstanding promises to be
136  /// fulfilled.
137  std::queue<MessageData> dataQueue;
138  /// Maximum number of messages to store in dataQueue. 0 means no limit.
140  /// Promises to be fulfilled when data is available.
141  std::queue<std::promise<MessageData>> promiseQueue;
142 };
143 
144 /// Services provide connections to 'bundles' -- collections of named,
145 /// unidirectional communication channels. This class provides access to those
146 /// ChannelPorts.
147 class BundlePort {
148 public:
149  /// Compute the direction of a channel given the bundle direction and the
150  /// bundle port's direction.
151  static bool isWrite(BundleType::Direction bundleDir) {
152  return bundleDir == BundleType::Direction::To;
153  }
154 
155  /// Construct a port.
156  BundlePort(AppID id, std::map<std::string, ChannelPort &> channels);
157  virtual ~BundlePort() = default;
158 
159  /// Get the ID of the port.
160  AppID getID() const { return id; }
161 
162  /// Get access to the raw byte streams of a channel. Intended for internal
163  /// usage and binding to other languages (e.g. Python) which have their own
164  /// message serialization code. Exposed publicly as an escape hatch, but
165  /// ordinary users should not use. You have been warned.
166  WriteChannelPort &getRawWrite(const std::string &name) const;
167  ReadChannelPort &getRawRead(const std::string &name) const;
168  const std::map<std::string, ChannelPort &> &getChannels() const {
169  return channels;
170  }
171 
172  /// Cast this Bundle port to a subclass which is actually useful. Returns
173  /// nullptr if the cast fails.
174  // TODO: this probably shouldn't be 'const', but bundle ports' user access are
175  // const. Change that.
176  template <typename T>
177  T *getAs() const {
178  return const_cast<T *>(dynamic_cast<const T *>(this));
179  }
180 
181 private:
183  std::map<std::string, ChannelPort &> channels;
184 };
185 
186 } // namespace esi
187 
188 #endif // ESI_PORTS_H
Services provide connections to 'bundles' – collections of named, unidirectional communication channe...
Definition: Ports.h:147
virtual ~BundlePort()=default
std::map< std::string, ChannelPort & > channels
Definition: Ports.h:183
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
AppID id
Definition: Ports.h:182
const std::map< std::string, ChannelPort & > & getChannels() const
Definition: Ports.h:168
T * getAs() const
Cast this Bundle port to a subclass which is actually useful.
Definition: Ports.h:177
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:151
BundlePort(AppID id, std::map< std::string, ChannelPort & > channels)
Construct a port.
Definition: Ports.cpp:22
AppID getID() const
Get the ID of the port.
Definition: Ports.h:160
Unidirectional channels are the basic communication primitive between the host and accelerator.
Definition: Ports.h:33
virtual void disconnect()
Definition: Ports.h:44
ChannelPort(const Type *type)
Definition: Ports.h:35
virtual void connect(std::optional< unsigned > bufferSize=std::nullopt)
Set up a connection to the accelerator.
Definition: Ports.h:41
virtual void connectImpl(std::optional< unsigned > bufferSize)
Called by all connect methods to let backends initiate the underlying connections.
Definition: Ports.h:53
const Type * type
Definition: Ports.h:49
const Type * getType() const
Definition: Ports.h:46
virtual ~ChannelPort()
Definition: Ports.h:36
A logical chunk of data representing serialized data.
Definition: Common.h:86
A ChannelPort which reads data from the accelerator.
Definition: Ports.h:69
virtual std::future< MessageData > readAsync()
Asynchronous read.
Definition: Ports.cpp:77
std::mutex pollingM
Mutex to protect the two queues used for polling.
Definition: Ports.h:134
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:127
Mode
Indicates the current mode of the channel.
Definition: Ports.h:123
std::queue< MessageData > dataQueue
Store incoming data here if there are no outstanding promises to be fulfilled.
Definition: Ports.h:137
static constexpr uint64_t DefaultMaxDataQueueMsgs
Default max data queue size set at connect time.
Definition: Ports.h:96
std::queue< std::promise< MessageData > > promiseQueue
Promises to be fulfilled when data is available.
Definition: Ports.h:141
void setMaxDataQueueMsgs(uint64_t maxMsgs)
Set maximum number of messages to store in the dataQueue.
Definition: Ports.h:119
uint64_t maxDataQueueMsgs
Maximum number of messages to store in dataQueue. 0 means no limit.
Definition: Ports.h:139
virtual void disconnect() override
Definition: Ports.h:74
virtual void read(MessageData &outData)
Specify a buffer to read into.
Definition: Ports.h:107
ReadChannelPort(const Type *type)
Definition: Ports.h:72
Root class of the ESI type system.
Definition: Types.h:27
A ChannelPort which sends data to the accelerator.
Definition: Ports.h:57
virtual void write(const MessageData &)=0
A very basic write API. Will likely change for performance reasons.
Definition: esi.py:1