CIRCT  19.0.0git
Services.cpp
Go to the documentation of this file.
1 //===- StdServices.cpp - implementations of std services ------------------===//
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 // (lib/dialect/ESI/runtime/cpp/lib/backends/Cosim.cpp).
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #include "esi/Services.h"
17 #include "esi/Accelerator.h"
18 
19 #include "zlib.h"
20 
21 #include <cassert>
22 #include <stdexcept>
23 
24 using namespace esi;
25 using namespace esi::services;
26 
27 std::string SysInfo::getServiceSymbol() const { return "__builtin_SysInfo"; }
28 
29 // Allocate 10MB for the uncompressed manifest. This should be plenty.
30 constexpr uint32_t MAX_MANIFEST_SIZE = 10 << 20;
31 /// Get the compressed manifest, uncompress, and return it.
32 std::string SysInfo::getJsonManifest() const {
33  std::vector<uint8_t> compressed = getCompressedManifest();
34  std::vector<Bytef> dst(MAX_MANIFEST_SIZE);
35  uLongf dstSize = MAX_MANIFEST_SIZE;
36  int rc =
37  uncompress(dst.data(), &dstSize, compressed.data(), compressed.size());
38  if (rc != Z_OK)
39  throw std::runtime_error("zlib uncompress failed with rc=" +
40  std::to_string(rc));
41  return std::string(reinterpret_cast<char *>(dst.data()), dstSize);
42 }
43 
44 std::string MMIO::getServiceSymbol() const { return "__builtin_MMIO"; }
45 
46 MMIOSysInfo::MMIOSysInfo(const MMIO *mmio) : mmio(mmio) {}
47 
48 uint32_t MMIOSysInfo::getEsiVersion() const {
49  uint64_t reg;
50  if ((reg = mmio->read(MetadataOffset)) != MagicNumber)
51  throw std::runtime_error("Invalid magic number: " + toHex(reg));
52  return mmio->read(MetadataOffset + 8);
53 }
54 
55 std::vector<uint8_t> MMIOSysInfo::getCompressedManifest() const {
56  uint64_t version = getEsiVersion();
57  if (version != 0)
58  throw std::runtime_error("Unsupported ESI header version: " +
59  std::to_string(version));
60  uint64_t manifestPtr = mmio->read(MetadataOffset + 0x10);
61  uint64_t size = mmio->read(manifestPtr);
62  uint64_t numWords = (size + 7) / 8;
63  std::vector<uint64_t> manifestWords(numWords);
64  for (size_t i = 0; i < numWords; ++i)
65  manifestWords[i] = mmio->read(manifestPtr + 8 + (i * 8));
66 
67  std::vector<uint8_t> manifest;
68  for (size_t i = 0; i < size; ++i) {
69  uint64_t word = manifestWords[i / 8];
70  manifest.push_back(word >> (8 * (i % 8)));
71  }
72  return manifest;
73 }
74 
75 std::string HostMem::getServiceSymbol() const { return "__builtin_HostMem"; }
76 
78  const ServiceImplDetails &details,
79  const HWClientDetails &clients)
80  : id(idPath) {
81  if (auto f = details.find("service"); f != details.end()) {
82  serviceSymbol = std::any_cast<std::string>(f->second);
83  // Strip off initial '@'.
84  serviceSymbol = serviceSymbol.substr(1);
85  }
86 }
87 
89  const std::string &implName,
90  ServiceImplDetails details, HWClientDetails clients) {
91  if (auto f = details.find("service"); f != details.end())
92  // Strip off initial '@'.
93  symbol = std::any_cast<std::string>(f->second).substr(1);
94 }
95 
96 std::string FuncService::getServiceSymbol() const { return symbol; }
97 
100  const std::map<std::string, ChannelPort &> &channels,
101  AcceleratorConnection &acc) const {
102  return new Function(id.back(), channels);
103 }
104 
106  AppID id, const std::map<std::string, ChannelPort &> &channels)
107  : ServicePort(id, channels),
108  arg(dynamic_cast<WriteChannelPort &>(channels.at("arg"))),
109  result(dynamic_cast<ReadChannelPort &>(channels.at("result"))) {
110  assert(channels.size() == 2 && "FuncService must have exactly two channels");
111 }
112 
114  WriteChannelPort &arg,
115  ReadChannelPort &result) {
116  return new Function(id, {{"arg", arg}, {"result", result}});
117 }
118 
120  arg.connect();
121  result.connect();
122 }
123 
124 std::future<MessageData>
126  std::scoped_lock<std::mutex> lock(callMutex);
127  arg.write(argData);
128  return result.readAsync();
129 }
130 
132  std::string implName, ServiceImplDetails details,
133  HWClientDetails clients) {
134  if (auto f = details.find("service"); f != details.end())
135  // Strip off initial '@'.
136  symbol = std::any_cast<std::string>(f->second).substr(1);
137 }
138 
139 std::string CallService::getServiceSymbol() const { return symbol; }
140 
141 ServicePort *
143  const std::map<std::string, ChannelPort &> &channels,
144  AcceleratorConnection &acc) const {
145  return new Callback(acc, id.back(), channels);
146 }
147 
149  AcceleratorConnection &acc, AppID id,
150  const std::map<std::string, ChannelPort &> &channels)
151  : ServicePort(id, channels),
152  arg(dynamic_cast<ReadChannelPort &>(channels.at("arg"))),
153  result(dynamic_cast<WriteChannelPort &>(channels.at("result"))),
154  acc(acc) {
155  if (channels.size() != 2)
156  throw std::runtime_error("CallService must have exactly two channels");
157 }
158 
160  std::function<MessageData(const MessageData &)> callback, bool quick) {
161  result.connect();
162  if (quick) {
163  // If it's quick, we can just call the callback directly.
164  arg.connect([this, callback](MessageData argMsg) -> bool {
165  MessageData resultMsg = callback(std::move(argMsg));
166  this->result.write(std::move(resultMsg));
167  return true;
168  });
169  } else {
170  // If it's not quick, we need to use the service thread.
171  arg.connect();
172  acc.getServiceThread()->addListener(
173  {&arg},
174  [this, callback](ReadChannelPort *, MessageData argMsg) -> void {
175  MessageData resultMsg = callback(std::move(argMsg));
176  this->result.write(std::move(resultMsg));
177  });
178  }
179 }
180 
182  Service::Type svcType, AppIDPath id,
183  std::string implName,
184  ServiceImplDetails details,
185  HWClientDetails clients) {
186  // TODO: Add a proper registration mechanism.
187  if (svcType == typeid(FuncService))
188  return new FuncService(acc, id, implName, details, clients);
189  if (svcType == typeid(CallService))
190  return new CallService(acc, id, implName, details, clients);
191  return nullptr;
192 }
193 
195  // TODO: Add a proper registration mechanism.
196  if (svcName == "esi.service.std.func")
197  return typeid(FuncService);
198  if (svcName == "esi.service.std.call")
199  return typeid(CallService);
200  return typeid(CustomService);
201 }
assert(baseType &&"element must be base type")
constexpr uint32_t MAX_MANIFEST_SIZE
Definition: Services.cpp:30
Abstract class representing a connection to an accelerator.
Definition: Accelerator.h:78
std::map< std::string, ChannelPort & > channels
Definition: Ports.h:183
Bundles represent a collection of channels.
Definition: Types.h:44
A logical chunk of data representing serialized data.
Definition: Common.h:86
A ChannelPort which reads data from the accelerator.
Definition: Ports.h:69
A ChannelPort which sends data to the accelerator.
Definition: Ports.h:57
A function call which gets attached to a service port.
Definition: Services.h:199
Callback(AcceleratorConnection &acc, AppID id, const std::map< std::string, ChannelPort & > &channels)
Definition: Services.cpp:148
void connect(std::function< MessageData(const MessageData &)> callback, bool quick=false)
Connect a callback to code which will be executed when the accelerator invokes the callback.
Definition: Services.cpp:159
Service for servicing function calls from the accelerator.
Definition: Services.h:188
CallService(AcceleratorConnection *acc, AppIDPath id, std::string implName, ServiceImplDetails details, HWClientDetails clients)
Definition: Services.cpp:131
virtual std::string getServiceSymbol() const override
Definition: Services.cpp:139
virtual ServicePort * getPort(AppIDPath id, const BundleType *type, const std::map< std::string, ChannelPort & > &, AcceleratorConnection &) const override
Get specialized port for this service to attach to the given appid path.
Definition: Services.cpp:142
A service for which there are no standard services registered.
Definition: Services.h:61
CustomService(AppIDPath idPath, const ServiceImplDetails &details, const HWClientDetails &clients)
Definition: Services.cpp:77
A function call which gets attached to a service port.
Definition: Services.h:166
std::future< MessageData > call(const MessageData &arg)
Definition: Services.cpp:125
static Function * get(AppID id, WriteChannelPort &arg, ReadChannelPort &result)
Definition: Services.cpp:113
Function(AppID id, const std::map< std::string, ChannelPort & > &channels)
Definition: Services.cpp:105
Service for calling functions.
Definition: Services.h:154
virtual std::string getServiceSymbol() const override
Definition: Services.cpp:96
virtual ServicePort * getPort(AppIDPath id, const BundleType *type, const std::map< std::string, ChannelPort & > &, AcceleratorConnection &) const override
Get specialized port for this service to attach to the given appid path.
Definition: Services.cpp:99
FuncService(AcceleratorConnection *acc, AppIDPath id, const std::string &implName, ServiceImplDetails details, HWClientDetails clients)
Definition: Services.cpp:88
virtual std::string getServiceSymbol() const override
Definition: Services.cpp:75
virtual std::vector< uint8_t > getCompressedManifest() const override
Return the zlib compressed JSON system manifest.
Definition: Services.cpp:55
uint32_t getEsiVersion() const override
Get the ESI version number to check version compatibility.
Definition: Services.cpp:48
MMIOSysInfo(const MMIO *)
Definition: Services.cpp:46
virtual uint64_t read(uint32_t addr) const =0
virtual std::string getServiceSymbol() const override
Definition: Services.cpp:44
Add a custom interface to a service client at a particular point in the design hierarchy.
Definition: Services.h:34
static Service::Type lookupServiceType(const std::string &)
Resolve a service type from a string.
Definition: Services.cpp:194
static Service * createService(AcceleratorConnection *acc, Service::Type svcType, AppIDPath id, std::string implName, ServiceImplDetails details, HWClientDetails clients)
Create a service instance from the given details.
Definition: Services.cpp:181
Parent class of all APIs modeled as 'services'.
Definition: Services.h:42
const std::type_info & Type
Definition: Services.h:44
virtual std::string getJsonManifest() const
Return the JSON-formatted system manifest.
Definition: Services.cpp:32
virtual std::vector< uint8_t > getCompressedManifest() const =0
Return the zlib compressed JSON system manifest.
virtual std::string getServiceSymbol() const override
Definition: Services.cpp:27
Definition: esi.py:1
constexpr uint64_t MagicNumber
Definition: Accelerator.h:47
std::map< std::string, std::any > ServiceImplDetails
Definition: Common.h:81
std::string toHex(uint32_t val)
Definition: Common.cpp:20
constexpr uint32_t MetadataOffset
Definition: Accelerator.h:44
std::vector< HWClientDetail > HWClientDetails
Definition: Common.h:80
def reg(value, clock, reset=None, reset_value=None, name=None, sym_name=None)
Definition: seq.py:20