32 return conn->
getService(service,
id, implName, details, clients);
45 uncompress(dst.data(), &dstSize, compressed.data(), compressed.size());
47 throw std::runtime_error(
"zlib uncompress failed with rc=" +
49 return std::string(
reinterpret_cast<char *
>(dst.data()), dstSize);
59 auto offsetIter = client.implOptions.find(
"offset");
60 if (offsetIter == client.implOptions.end())
61 throw std::runtime_error(
"MMIO client missing 'offset' option");
62 Constant offset = std::any_cast<Constant>(offsetIter->second);
63 uint64_t offsetVal = std::any_cast<uint64_t>(offset.
value);
64 if (offsetVal >= 1ull << 32)
65 throw std::runtime_error(
"MMIO client offset mustn't exceed 32 bits");
67 auto sizeIter = client.implOptions.find(
"size");
68 if (sizeIter == client.implOptions.end())
69 throw std::runtime_error(
"MMIO client missing 'size' option");
70 Constant size = std::any_cast<Constant>(sizeIter->second);
71 uint64_t sizeVal = std::any_cast<uint64_t>(size.
value);
72 if (sizeVal >= 1ull << 32)
73 throw std::runtime_error(
"MMIO client size mustn't exceed 32 bits");
83 const std::map<std::string, ChannelPort &> &,
85 auto regionIter =
regions.find(
id);
86 if (regionIter ==
regions.end())
93 class MMIOPassThrough :
public MMIO {
98 :
MMIO(
ctxt, idPath, implName, details, clients), parent(parent) {}
99 uint64_t read(uint32_t addr)
const override {
return parent->
read(addr); }
100 void write(uint32_t addr, uint64_t data)
override {
101 parent->write(addr, data);
113 if (service !=
typeid(
MMIO))
116 return new MMIOPassThrough(conn->
getCtxt(),
id, implName, details, clients,
125 :
ServicePort(id, {}), parent(parent), desc(desc) {}
127 if (addr >= desc.size)
128 throw std::runtime_error(
"MMIO read out of bounds: " +
toHex(addr));
129 return parent->read(desc.base + addr);
132 if (addr >= desc.size)
133 throw std::runtime_error(
"MMIO write out of bounds: " +
toHex(addr));
134 parent->write(desc.base + addr, data);
142 throw std::runtime_error(
"Invalid magic number: " +
toHex(
reg));
149 throw std::runtime_error(
"Unsupported ESI header version: " +
150 std::to_string(version));
152 uint64_t size =
mmio->
read(manifestPtr);
153 uint64_t numWords = (size + 7) / 8;
154 std::vector<uint64_t> manifestWords(numWords);
155 for (
size_t i = 0; i < numWords; ++i)
156 manifestWords[i] =
mmio->
read(manifestPtr + 8 + (i * 8));
158 std::vector<uint8_t> manifest;
159 for (
size_t i = 0; i < size; ++i) {
160 uint64_t word = manifestWords[i / 8];
161 manifest.push_back(word >> (8 * (i % 8)));
172 if (
auto f = details.find(
"service"); f != details.end()) {
180 const std::string &implName,
182 if (
auto f = details.find(
"service"); f != details.end())
184 symbol = std::any_cast<std::string>(f->second).substr(1);
191 const std::map<std::string, ChannelPort &> &channels,
193 return new Function(
id.back(), channels);
197 AppID id,
const std::map<std::string, ChannelPort &> &channels)
201 assert(
channels.size() == 2 &&
"FuncService must have exactly two channels");
207 return new Function(
id, {{
"arg", arg}, {
"result", result}});
215 std::future<MessageData>
217 std::scoped_lock<std::mutex> lock(callMutex);
219 return result.readAsync();
225 if (
auto f = details.find(
"service"); f != details.end())
227 symbol = std::any_cast<std::string>(f->second).substr(1);
234 const std::map<std::string, ChannelPort &> &channels,
236 return new Callback(acc,
id.back(), channels);
240 const std::string &name) {
241 auto f = channels.find(name);
242 if (f == channels.end())
243 throw std::runtime_error(
"CallService must have an '" + name +
"' channel");
248 const std::string &name) {
249 auto f = channels.find(name);
250 if (f == channels.end())
251 throw std::runtime_error(
"CallService must have an '" + name +
"' channel");
257 const std::map<std::string, ChannelPort &> &channels)
259 result(
getWrite(channels,
"result")), acc(acc) {
261 throw std::runtime_error(
"CallService must have exactly two channels");
268 return new Callback(acc,
id, {{
"arg", arg}, {
"result", result}});
276 arg.connect([
this, callback](
MessageData argMsg) ->
bool {
277 MessageData resultMsg = callback(std::move(argMsg));
278 this->result.write(std::move(resultMsg));
284 acc.getServiceThread()->addListener(
287 MessageData resultMsg = callback(std::move(argMsg));
288 this->result.write(std::move(resultMsg));
295 std::string implName,
300 return new FuncService(acc,
id, implName, details, clients);
302 return new CallService(acc,
id, implName, details, clients);
308 if (svcName ==
"esi.service.std.func")
310 if (svcName ==
"esi.service.std.call")
assert(baseType &&"element must be base type")
WriteChannelPort & getWrite(const std::map< std::string, ChannelPort & > &channels, const std::string &name)
constexpr uint32_t MAX_MANIFEST_SIZE
ReadChannelPort & getRead(const std::map< std::string, ChannelPort & > &channels, const std::string &name)
Abstract class representing a connection to an accelerator.
Context & getCtxt() const
ServiceClass * getService(AppIDPath id={}, std::string implName={}, ServiceImplDetails details={}, HWClientDetails clients={})
Get a typed reference to a particular service type.
std::map< std::string, ChannelPort & > channels
Bundles represent a collection of channels.
AcceleratorConnections, Accelerators, and Manifests must all share a context.
A logical chunk of data representing serialized data.
A ChannelPort which reads data from the accelerator.
A ChannelPort which sends data to the accelerator.
A function call which gets attached to a service port.
static Callback * get(AcceleratorConnection &acc, AppID id, WriteChannelPort &result, ReadChannelPort &arg)
Callback(AcceleratorConnection &acc, AppID id, const std::map< std::string, ChannelPort & > &channels)
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.
Service for servicing function calls from the accelerator.
CallService(AcceleratorConnection *acc, AppIDPath id, std::string implName, ServiceImplDetails details, HWClientDetails clients)
virtual std::string getServiceSymbol() const override
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.
A service for which there are no standard services registered.
CustomService(AppIDPath idPath, const ServiceImplDetails &details, const HWClientDetails &clients)
std::string serviceSymbol
A function call which gets attached to a service port.
std::future< MessageData > call(const MessageData &arg)
static Function * get(AppID id, WriteChannelPort &arg, ReadChannelPort &result)
Function(AppID id, const std::map< std::string, ChannelPort & > &channels)
Service for calling functions.
virtual std::string getServiceSymbol() const override
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.
FuncService(AcceleratorConnection *acc, AppIDPath id, const std::string &implName, ServiceImplDetails details, HWClientDetails clients)
virtual std::string getServiceSymbol() const override
virtual std::vector< uint8_t > getCompressedManifest() const override
Return the zlib compressed JSON system manifest.
uint32_t getEsiVersion() const override
Get the ESI version number to check version compatibility.
MMIOSysInfo(const MMIO *)
A "slice" of some parent MMIO space.
virtual uint64_t read(uint32_t addr) const
Read a 64-bit value from this region, not the global address space.
MMIORegion(AppID id, MMIO *parent, RegionDescriptor desc)
virtual void write(uint32_t addr, uint64_t data)
Write a 64-bit value to this region, not the global address space.
virtual uint64_t read(uint32_t addr) const =0
Read a 64-bit value from the global MMIO space.
virtual Service * getChildService(AcceleratorConnection *conn, Service::Type service, AppIDPath id={}, std::string implName={}, ServiceImplDetails details={}, HWClientDetails clients={}) override
If the service is a MMIO service, return a region of the MMIO space which peers into ours.
std::map< AppIDPath, RegionDescriptor > regions
MMIO base address table.
static constexpr std::string_view StdName
virtual ServicePort * getPort(AppIDPath id, const BundleType *type, const std::map< std::string, ChannelPort & > &, AcceleratorConnection &) const override
Get a MMIO region port for a particular region descriptor.
virtual std::string getServiceSymbol() const override
Add a custom interface to a service client at a particular point in the design hierarchy.
static Service::Type lookupServiceType(const std::string &)
Resolve a service type from a string.
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.
Parent class of all APIs modeled as 'services'.
const std::type_info & Type
virtual Service * getChildService(AcceleratorConnection *conn, Service::Type service, AppIDPath id={}, std::string implName={}, ServiceImplDetails details={}, HWClientDetails clients={})
Create a "child" service of this service.
virtual std::string getJsonManifest() const
Return the JSON-formatted system manifest.
virtual std::vector< uint8_t > getCompressedManifest() const =0
Return the zlib compressed JSON system manifest.
virtual std::string getServiceSymbol() const override
constexpr uint64_t MagicNumber
std::map< std::string, std::any > ServiceImplDetails
std::string toHex(uint32_t val)
constexpr uint32_t MetadataOffset
std::vector< HWClientDetail > HWClientDetails
def reg(value, clock, reset=None, reset_value=None, name=None, sym_name=None)
A description of a hardware client.
Describe a region (slice) of MMIO space.