CIRCT 20.0.0git
Loading...
Searching...
No Matches
Manifest.cpp
Go to the documentation of this file.
1//===- Manifest.cpp - Metadata on the accelerator -------------------------===//
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 (lib/dialect/ESI/runtime/cpp/).
12//
13//===----------------------------------------------------------------------===//
14
15#include "esi/Manifest.h"
16#include "esi/Accelerator.h"
17#include "esi/Services.h"
18
19#include <nlohmann/json.hpp>
20#include <sstream>
21
22using namespace ::esi;
23using ServiceTable = AcceleratorConnection::ServiceTable;
24
25// This is a proxy class to the manifest JSON. It is used to avoid having to
26// include the JSON parser in the header. Forward references don't work since
27// nlohmann::json is a rather complex template.
28//
29// Plus, it allows us to hide some implementation functions from the header
30// file.
32 friend class ::esi::Manifest;
33
34public:
35 Impl(Context &ctxt, const std::string &jsonManifest);
36
37 auto at(const std::string &key) const { return manifestJson.at(key); }
38
39 // Get the module info (if any) for the module instance in 'json'.
40 std::optional<ModuleInfo> getModInfo(const nlohmann::json &) const;
41
42 /// Go through the "service_decls" section of the manifest and populate the
43 /// services table as appropriate.
44 void scanServiceDecls(AcceleratorConnection &, const nlohmann::json &,
45 ServiceTable &) const;
46
47 /// Get a Service for the service specified in 'json'. Update the
48 /// activeServices table.
49 services::Service *getService(AppIDPath idPath, AcceleratorConnection &,
50 const nlohmann::json &,
51 ServiceTable &activeServices) const;
52
53 /// Get all the services in the description of an instance. Update the active
54 /// services table.
55 std::vector<services::Service *>
56 getServices(AppIDPath idPath, AcceleratorConnection &, const nlohmann::json &,
57 ServiceTable &activeServices) const;
58
59 /// Get the bundle ports for the instance at 'idPath' and specified in
60 /// 'instJson'. Look them up in 'activeServies'.
61 std::vector<std::unique_ptr<BundlePort>>
62 getBundlePorts(AcceleratorConnection &acc, AppIDPath idPath,
63 const ServiceTable &activeServices,
64 const nlohmann::json &instJson) const;
65
66 /// Build the set of child instances (recursively) for the module instance
67 /// description.
68 std::vector<std::unique_ptr<Instance>>
69 getChildInstances(AppIDPath idPath, AcceleratorConnection &acc,
70 const ServiceTable &activeServices,
71 const nlohmann::json &instJson) const;
72
73 /// Get a single child instance. Implicitly copy the active services table so
74 /// that it can be safely updated for the child's branch of the tree.
75 std::unique_ptr<Instance>
76 getChildInstance(AppIDPath idPath, AcceleratorConnection &acc,
77 ServiceTable activeServices,
78 const nlohmann::json &childJson) const;
79
80 /// Parse all the types and populate the types table.
81 void populateTypes(const nlohmann::json &typesJson);
82
83 /// Get the ordered list of types from the manifest.
84 const std::vector<const Type *> &getTypeTable() const { return _typeTable; }
85
86 /// Build a dynamic API for the Accelerator connection 'acc' based on the
87 /// manifest stored herein.
88 std::unique_ptr<Accelerator>
89 buildAccelerator(AcceleratorConnection &acc) const;
90
91 const Type *parseType(const nlohmann::json &typeJson);
92
93 const std::map<std::string, const ModuleInfo> &getSymbolInfo() const {
94 return symbolInfoCache;
95 }
96
97private:
98 Context &ctxt;
99 std::vector<const Type *> _typeTable;
100
101 std::optional<const Type *> getType(Type::ID id) const {
102 return ctxt.getType(id);
103 }
104
105 std::any getAny(const nlohmann::json &value) const;
106 void parseModuleMetadata(ModuleInfo &info, const nlohmann::json &mod) const;
107 void parseModuleConsts(ModuleInfo &info, const nlohmann::json &mod) const;
108
109 // The parsed json.
110 nlohmann::json manifestJson;
111 // Cache the module info for each symbol.
112 std::map<std::string, const ModuleInfo> symbolInfoCache;
113};
114
115//===----------------------------------------------------------------------===//
116// Simple JSON -> object parsers.
117//===----------------------------------------------------------------------===//
118
119static std::optional<AppID> parseID(const nlohmann::json &jsonID) {
120 if (!jsonID.is_object())
121 return std::nullopt;
122 std::optional<uint32_t> idx;
123 if (jsonID.contains("index"))
124 idx = jsonID.at("index").get<uint32_t>();
125 if (jsonID.contains("name") && jsonID.size() <= 2)
126 return AppID(jsonID.at("name").get<std::string>(), idx);
127 return std::nullopt;
128}
129
130static AppID parseIDChecked(const nlohmann::json &jsonID) {
131 std::optional<AppID> id = parseID(jsonID);
132 if (!id)
133 throw std::runtime_error("Malformed manifest: invalid appID");
134 return *id;
135}
136static AppIDPath parseIDPath(const nlohmann::json &jsonIDPath) {
137 AppIDPath ret;
138 for (auto &idJson : jsonIDPath)
139 ret.push_back(parseIDChecked(idJson));
140 return ret;
141}
142
143static ServicePortDesc parseServicePort(const nlohmann::json &jsonPort) {
144 return ServicePortDesc{jsonPort.at("serviceName").get<std::string>(),
145 jsonPort.at("port").get<std::string>()};
146}
147
148/// Convert the json value to a 'std::any', which can be exposed outside of this
149/// file.
150std::any Manifest::Impl::getAny(const nlohmann::json &value) const {
151 auto getObject = [this](const nlohmann::json &json) -> std::any {
152 std::map<std::string, std::any> ret;
153 for (auto &e : json.items())
154 ret[e.key()] = getAny(e.value());
155
156 // If this can be converted to a constant, do so.
157 if (ret.size() != 2 || !ret.contains("type") || !ret.contains("value"))
158 return ret;
159 std::any value = ret.at("value");
160 std::any typeID = ret.at("type");
161 if (typeID.type() != typeid(std::string))
162 return ret;
163 std::optional<const Type *> type =
164 getType(std::any_cast<std::string>(type));
165 if (!type)
166 return ret;
167 // TODO: Check or guide the conversion of the value to the type based on the
168 // type.
169 return Constant{value, type};
170 };
171
172 auto getArray = [this](const nlohmann::json &json) -> std::any {
173 std::vector<std::any> ret;
174 for (auto &e : json)
175 ret.push_back(getAny(e));
176 return ret;
177 };
178
179 auto getValue = [&](const nlohmann::json &innerValue) -> std::any {
180 if (innerValue.is_string())
181 return innerValue.get<std::string>();
182 else if (innerValue.is_number_unsigned())
183 return innerValue.get<uint64_t>();
184 else if (innerValue.is_number_integer())
185 return innerValue.get<int64_t>();
186 else if (innerValue.is_number_float())
187 return innerValue.get<double>();
188 else if (innerValue.is_boolean())
189 return innerValue.get<bool>();
190 else if (innerValue.is_null())
191 return innerValue.get<std::nullptr_t>();
192 else if (innerValue.is_object())
193 return getObject(innerValue);
194 else if (innerValue.is_array())
195 return getArray(innerValue);
196 else
197 throw std::runtime_error("Unknown type in manifest: " +
198 innerValue.dump(2));
199 };
200
201 std::optional<AppID> appid = parseID(value);
202 if (appid)
203 return *appid;
204 if (!value.is_object() || !value.contains("type") || !value.contains("value"))
205 return getValue(value);
206 return Constant{getValue(value.at("value")), getType(value.at("type"))};
207}
208
210 const nlohmann::json &mod) const {
211 for (auto &extra : mod.items())
212 if (extra.key() != "name" && extra.key() != "summary" &&
213 extra.key() != "version" && extra.key() != "repo" &&
214 extra.key() != "commitHash")
215 info.extra[extra.key()] = getAny(extra.value());
216
217 auto value = [&](const std::string &key) -> std::optional<std::string> {
218 auto f = mod.find(key);
219 if (f == mod.end())
220 return std::nullopt;
221 return f.value();
222 };
223 info.name = value("name");
224 info.summary = value("summary");
225 info.version = value("version");
226 info.repo = value("repo");
227 info.commitHash = value("commitHash");
228}
229
231 const nlohmann::json &mod) const {
232 for (auto &item : mod.items()) {
233 std::any value = getAny(item.value());
234 auto *c = std::any_cast<Constant>(&value);
235 if (c)
236 info.constants[item.key()] = *c;
237 else
238 // If the value isn't a "proper" constant, present it as one with no type.
239 info.constants[item.key()] = Constant{value, std::nullopt};
240 }
241}
242
243//===----------------------------------------------------------------------===//
244// Manifest::Impl class implementation.
245//===----------------------------------------------------------------------===//
246
247Manifest::Impl::Impl(Context &ctxt, const std::string &manifestStr)
248 : ctxt(ctxt) {
249 manifestJson = nlohmann::ordered_json::parse(manifestStr);
250
251 try {
252 // Populate the types table first since anything else might need it.
253 populateTypes(manifestJson.at("types"));
254
255 // Populate the symbol info cache.
256 for (auto &mod : manifestJson.at("modules")) {
257 ModuleInfo info;
258 if (mod.contains("symInfo"))
259 parseModuleMetadata(info, mod.at("symInfo"));
260 if (mod.contains("symConsts"))
261 parseModuleConsts(info, mod.at("symConsts"));
262 symbolInfoCache.insert(make_pair(mod.at("symbol"), info));
263 }
264 } catch (const std::exception &e) {
265 std::string msg = "malformed manifest: " + std::string(e.what());
266 if (manifestJson.at("apiVersion") == 0)
267 msg += " (schema version 0 is not considered stable)";
268 throw std::runtime_error(msg);
269 }
270}
271
272std::unique_ptr<Accelerator>
273Manifest::Impl::buildAccelerator(AcceleratorConnection &acc) const {
274 ServiceTable activeSvcs;
275
276 // Get the initial active services table. Update it as we descend down.
277 auto svcDecls = manifestJson.at("serviceDeclarations");
278 scanServiceDecls(acc, svcDecls, activeSvcs);
279
280 // Get the services instantiated at the top level.
281 auto designJson = manifestJson.at("design");
282 std::vector<services::Service *> services =
283 getServices({}, acc, designJson, activeSvcs);
284
285 // Get the ports at the top level.
286 auto ports = getBundlePorts(acc, {}, activeSvcs, designJson);
287
288 return std::make_unique<Accelerator>(
289 getModInfo(designJson),
290 getChildInstances({}, acc, activeSvcs, designJson), services, ports);
291}
292
293std::optional<ModuleInfo>
294Manifest::Impl::getModInfo(const nlohmann::json &json) const {
295 auto instOfIter = json.find("instOf");
296 if (instOfIter == json.end())
297 return std::nullopt;
298 auto f = symbolInfoCache.find(instOfIter.value());
299 if (f != symbolInfoCache.end())
300 return f->second;
301 return std::nullopt;
302}
303
304void Manifest::Impl::scanServiceDecls(AcceleratorConnection &acc,
305 const nlohmann::json &svcDecls,
306 ServiceTable &activeServices) const {
307 for (auto &svcDecl : svcDecls) {
308 if (auto f = svcDecl.find("serviceName"); f != svcDecl.end()) {
309 // Get the implementation details.
310 ServiceImplDetails svcDetails;
311 for (auto &detail : svcDecl.items())
312 svcDetails[detail.key()] = getAny(detail.value());
313
314 // Create the service.
315 services::Service::Type svcId =
316 services::ServiceRegistry::lookupServiceType(f.value());
317 auto svc = acc.getService(svcId, /*id=*/{}, /*implName=*/"",
318 /*details=*/svcDetails, /*clients=*/{});
319 if (svc)
320 activeServices[svcDecl.at("symbol")] = svc;
321 }
322 }
323}
324
325std::vector<std::unique_ptr<Instance>>
326Manifest::Impl::getChildInstances(AppIDPath idPath, AcceleratorConnection &acc,
327 const ServiceTable &activeServices,
328 const nlohmann::json &instJson) const {
329 std::vector<std::unique_ptr<Instance>> ret;
330 auto childrenIter = instJson.find("children");
331 if (childrenIter == instJson.end())
332 return ret;
333 for (auto &child : childrenIter.value())
334 ret.emplace_back(getChildInstance(idPath, acc, activeServices, child));
335 return ret;
336}
337
338std::unique_ptr<Instance>
339Manifest::Impl::getChildInstance(AppIDPath idPath, AcceleratorConnection &acc,
340 ServiceTable activeServices,
341 const nlohmann::json &child) const {
342 AppID childID = parseIDChecked(child.at("appID"));
343 idPath.push_back(childID);
344
345 std::vector<services::Service *> services =
346 getServices(idPath, acc, child, activeServices);
347
348 auto children = getChildInstances(idPath, acc, activeServices, child);
349 auto ports = getBundlePorts(acc, idPath, activeServices, child);
350 return std::make_unique<Instance>(parseIDChecked(child.at("appID")),
351 getModInfo(child), std::move(children),
352 services, ports);
353}
354
355services::Service *
356Manifest::Impl::getService(AppIDPath idPath, AcceleratorConnection &acc,
357 const nlohmann::json &svcJson,
358 ServiceTable &activeServices) const {
359
360 AppID id = parseIDChecked(svcJson.at("appID"));
361 idPath.push_back(id);
362
363 // Get all the client info, including the implementation details.
364 HWClientDetails clientDetails;
365 for (auto &client : svcJson.at("clientDetails")) {
366 HWClientDetail clientDetail;
367 for (auto &detail : client.items()) {
368 if (detail.key() == "relAppIDPath")
369 clientDetail.relPath = parseIDPath(detail.value());
370 else if (detail.key() == "servicePort")
371 clientDetail.port = parseServicePort(detail.value());
372 else if (detail.key() == "channelAssignments") {
373 for (auto &chan : detail.value().items()) {
374 ChannelAssignment chanAssign;
375 for (auto &assign : chan.value().items())
376 if (assign.key() == "type")
377 chanAssign.type = assign.value();
378 else
379 chanAssign.implOptions[assign.key()] = getAny(assign.value());
380 clientDetail.channelAssignments[chan.key()] = chanAssign;
381 }
382 } else
383 clientDetail.implOptions[detail.key()] = getAny(detail.value());
384 }
385 clientDetails.push_back(clientDetail);
386 }
387
388 // Get the implementation details.
389 ServiceImplDetails svcDetails;
390 std::string implName;
391 std::string service;
392 for (auto &detail : svcJson.items()) {
393 if (detail.key() == "appID" || detail.key() == "clientDetails")
394 continue;
395 if (detail.key() == "serviceImplName")
396 implName = detail.value();
397 else if (detail.key() == "service")
398 service = detail.value().get<std::string>();
399 else
400 svcDetails[detail.key()] = getAny(detail.value());
401 }
402
403 // Create the service.
404 services::Service *svc = nullptr;
405 auto activeServiceIter = activeServices.find(service);
406 if (activeServiceIter != activeServices.end()) {
407 services::Service::Type svcType =
408 services::ServiceRegistry::lookupServiceType(
409 activeServiceIter->second->getServiceSymbol());
410 svc = activeServiceIter->second->getChildService(
411 &acc, svcType, idPath, implName, svcDetails, clientDetails);
412 } else {
413 services::Service::Type svcType =
414 services::ServiceRegistry::lookupServiceType(service);
415 svc = acc.getService(svcType, idPath, implName, svcDetails, clientDetails);
416 }
417
418 if (svc)
419 // Update the active services table.
420 activeServices[service] = svc;
421 return svc;
422}
423
424std::vector<services::Service *>
425Manifest::Impl::getServices(AppIDPath idPath, AcceleratorConnection &acc,
426 const nlohmann::json &svcsJson,
427 ServiceTable &activeServices) const {
428 std::vector<services::Service *> ret;
429 auto svcsIter = svcsJson.find("services");
430 if (svcsIter == svcsJson.end())
431 return ret;
432
433 for (auto &svc : svcsIter.value())
434 ret.emplace_back(getService(idPath, acc, svc, activeServices));
435 return ret;
436}
437
438std::vector<std::unique_ptr<BundlePort>>
439Manifest::Impl::getBundlePorts(AcceleratorConnection &acc, AppIDPath idPath,
440 const ServiceTable &activeServices,
441 const nlohmann::json &instJson) const {
442 std::vector<std::unique_ptr<BundlePort>> ret;
443 auto clientPortsIter = instJson.find("clientPorts");
444 if (clientPortsIter == instJson.end())
445 return ret;
446
447 for (auto &content : clientPortsIter.value()) {
448 // Lookup the requested service in the active services table.
449 std::string serviceName = "";
450 if (auto f = content.find("servicePort"); f != content.end())
451 serviceName = parseServicePort(f.value()).name;
452 auto svcIter = activeServices.find(serviceName);
453 if (svcIter == activeServices.end()) {
454 // If a specific service isn't found, search for the default service
455 // (typically provided by a BSP).
456 if (svcIter = activeServices.find(""); svcIter == activeServices.end())
457 throw std::runtime_error(
458 "Malformed manifest: could not find active service '" +
459 serviceName + "'");
460 }
461 services::Service *svc = svcIter->second;
462
463 std::string typeName = content.at("typeID");
464 auto type = getType(typeName);
465 if (!type)
466 throw std::runtime_error(
467 "Malformed manifest: could not find port type '" + typeName + "'");
468 const BundleType *bundleType = dynamic_cast<const BundleType *>(*type);
469 if (!bundleType)
470 throw std::runtime_error("Malformed manifest: type '" + typeName +
471 "' is not a bundle type");
472
473 idPath.push_back(parseIDChecked(content.at("appID")));
474 std::map<std::string, ChannelPort &> portChannels =
475 acc.requestChannelsFor(idPath, bundleType, activeServices);
476
477 services::ServicePort *svcPort =
478 svc->getPort(idPath, bundleType, portChannels, acc);
479 if (svcPort)
480 ret.emplace_back(svcPort);
481 else
482 ret.emplace_back(new BundlePort(idPath.back(), portChannels));
483 // Since we share idPath between iterations, pop the last element before the
484 // next iteration.
485 idPath.pop_back();
486 }
487 return ret;
488}
489
490namespace {
491const Type *parseType(const nlohmann::json &typeJson, Context &ctxt);
492
493BundleType *parseBundleType(const nlohmann::json &typeJson, Context &cache) {
494 assert(typeJson.at("mnemonic") == "bundle");
495
496 std::vector<std::tuple<std::string, BundleType::Direction, const Type *>>
497 channels;
498 for (auto &chanJson : typeJson["channels"]) {
499 std::string dirStr = chanJson.at("direction");
500 BundleType::Direction dir;
501 if (dirStr == "to")
502 dir = BundleType::Direction::To;
503 else if (dirStr == "from")
504 dir = BundleType::Direction::From;
505 else
506 throw std::runtime_error("Malformed manifest: unknown direction '" +
507 dirStr + "'");
508 channels.emplace_back(chanJson.at("name"), dir,
509 parseType(chanJson["type"], cache));
510 }
511 return new BundleType(typeJson.at("id"), channels);
512}
513
514ChannelType *parseChannelType(const nlohmann::json &typeJson, Context &cache) {
515 assert(typeJson.at("mnemonic") == "channel");
516 return new ChannelType(typeJson.at("id"),
517 parseType(typeJson.at("inner"), cache));
518}
519
520Type *parseInt(const nlohmann::json &typeJson, Context &cache) {
521 assert(typeJson.at("mnemonic") == "int");
522 std::string sign = typeJson.at("signedness");
523 uint64_t width = typeJson.at("hwBitwidth");
524 Type::ID id = typeJson.at("id");
525
526 if (sign == "signed")
527 return new SIntType(id, width);
528 else if (sign == "unsigned")
529 return new UIntType(id, width);
530 else if (sign == "signless" && width == 0)
531 // By convention, a zero-width signless integer is a void type.
532 return new VoidType(id);
533 else if (sign == "signless" && width > 0)
534 return new BitsType(id, width);
535 else
536 throw std::runtime_error("Malformed manifest: unknown sign '" + sign + "'");
537}
538
539StructType *parseStruct(const nlohmann::json &typeJson, Context &cache) {
540 assert(typeJson.at("mnemonic") == "struct");
541 std::vector<std::pair<std::string, const Type *>> fields;
542 for (auto &fieldJson : typeJson["fields"])
543 fields.emplace_back(fieldJson.at("name"),
544 parseType(fieldJson["type"], cache));
545 return new StructType(typeJson.at("id"), fields);
546}
547
548ArrayType *parseArray(const nlohmann::json &typeJson, Context &cache) {
549 assert(typeJson.at("mnemonic") == "array");
550 uint64_t size = typeJson.at("size");
551 return new ArrayType(typeJson.at("id"),
552 parseType(typeJson.at("element"), cache), size);
553}
554
555using TypeParser = std::function<Type *(const nlohmann::json &, Context &)>;
556const std::map<std::string_view, TypeParser> typeParsers = {
557 {"bundle", parseBundleType},
558 {"channel", parseChannelType},
559 {"std::any", [](const nlohmann::json &typeJson,
560 Context &cache) { return new AnyType(typeJson.at("id")); }},
561 {"int", parseInt},
562 {"struct", parseStruct},
563 {"array", parseArray},
564
565};
566
567// Parse a type if it doesn't already exist in the cache.
568const Type *parseType(const nlohmann::json &typeJson, Context &cache) {
569 std::string id;
570 if (typeJson.is_string())
571 id = typeJson.get<std::string>();
572 else
573 id = typeJson.at("id");
574 if (std::optional<const Type *> t = cache.getType(id))
575 return *t;
576 if (typeJson.is_string())
577 throw std::runtime_error("malformed manifest: unknown type '" + id + "'");
578
579 Type *t;
580 std::string mnemonic = typeJson.at("mnemonic");
581 auto f = typeParsers.find(mnemonic);
582 if (f != typeParsers.end())
583 t = f->second(typeJson, cache);
584 else
585 // Types we don't know about are opaque.
586 t = new Type(id);
587
588 // Insert into the cache.
589 cache.registerType(t);
590 return t;
591}
592} // namespace
593
594const Type *Manifest::Impl::parseType(const nlohmann::json &typeJson) {
595 return ::parseType(typeJson, ctxt);
596}
597
598void Manifest::Impl::populateTypes(const nlohmann::json &typesJson) {
599 for (auto &typeJson : typesJson)
600 _typeTable.push_back(parseType(typeJson));
601}
602
603//===----------------------------------------------------------------------===//
604// Manifest class implementation.
605//===----------------------------------------------------------------------===//
606
607Manifest::Manifest(Context &ctxt, const std::string &jsonManifest)
608 : impl(new Impl(ctxt, jsonManifest)) {}
609
610Manifest::~Manifest() { delete impl; }
611
612uint32_t Manifest::getApiVersion() const {
613 return impl->at("apiVersion").get<uint32_t>();
614}
615
616std::vector<ModuleInfo> Manifest::getModuleInfos() const {
617 std::vector<ModuleInfo> ret;
618 for (auto &[symbol, info] : impl->getSymbolInfo())
619 ret.push_back(info);
620 return ret;
621}
622
623Accelerator *Manifest::buildAccelerator(AcceleratorConnection &acc) const {
624 try {
625 return acc.takeOwnership(impl->buildAccelerator(acc));
626 } catch (const std::exception &e) {
627 std::string msg = "malformed manifest: " + std::string(e.what());
628 if (getApiVersion() == 0)
629 msg += " (schema version 0 is not considered stable)";
630 throw std::runtime_error(msg);
631 }
632}
633
634const std::vector<const Type *> &Manifest::getTypeTable() const {
635 return impl->getTypeTable();
636}
637
638//===----------------------------------------------------------------------===//
639// POCO helpers.
640//===----------------------------------------------------------------------===//
641
642// Print a module info, including the extra metadata.
643std::ostream &operator<<(std::ostream &os, const ModuleInfo &m) {
644 auto printAny = [&os](std::any a) {
645 if (auto *c = std::any_cast<Constant>(&a))
646 a = std::any_cast<Constant>(a).value;
647
648 const std::type_info &t = a.type();
649 if (t == typeid(std::string))
650 os << std::any_cast<std::string>(a);
651 else if (t == typeid(int64_t))
652 os << std::any_cast<int64_t>(a);
653 else if (t == typeid(uint64_t))
654 os << std::any_cast<uint64_t>(a);
655 else if (t == typeid(double))
656 os << std::any_cast<double>(a);
657 else if (t == typeid(bool))
658 os << std::any_cast<bool>(a);
659 else if (t == typeid(std::nullptr_t))
660 os << "null";
661 else
662 os << "unknown";
663 };
664
665 if (m.name)
666 os << *m.name << " ";
667 if (m.version)
668 os << *m.version << " ";
669 if (m.repo || m.commitHash) {
670 os << "(";
671 if (m.repo)
672 os << *m.repo;
673 if (m.commitHash)
674 os << "@" << *m.commitHash;
675 os << ")";
676 }
677 if (m.summary)
678 os << ": " << *m.summary;
679 os << "\n";
680
681 if (!m.constants.empty()) {
682 os << " Constants:\n";
683 for (auto &e : m.constants) {
684 os << " " << e.first << ": ";
685 printAny(e.second);
686 os << "\n";
687 }
688 }
689
690 if (!m.extra.empty()) {
691 os << " Extra metadata:\n";
692 for (auto &e : m.extra) {
693 os << " " << e.first << ": ";
694 printAny(e.second);
695 os << "\n";
696 }
697 }
698 return os;
699}
700
701namespace esi {
702AppIDPath AppIDPath::operator+(const AppIDPath &b) {
703 AppIDPath ret = *this;
704 ret.insert(ret.end(), b.begin(), b.end());
705 return ret;
706}
707
708std::string AppIDPath::toStr() const {
709 std::ostringstream os;
710 os << *this;
711 return os.str();
712}
713
714bool operator<(const AppID &a, const AppID &b) {
715 if (a.name != b.name)
716 return a.name < b.name;
717 return a.idx < b.idx;
718}
719bool operator<(const AppIDPath &a, const AppIDPath &b) {
720 if (a.size() != b.size())
721 return a.size() < b.size();
722 for (size_t i = 0, e = a.size(); i < e; ++i)
723 if (a[i] != b[i])
724 return a[i] < b[i];
725 return false;
726}
727} // namespace esi
728
729std::ostream &operator<<(std::ostream &os, const AppID &id) {
730 os << id.name;
731 if (id.idx)
732 os << "[" << *id.idx << "]";
733 return os;
734}
735std::ostream &operator<<(std::ostream &os, const AppIDPath &path) {
736 for (size_t i = 0, e = path.size(); i < e; ++i) {
737 if (i > 0)
738 os << '.';
739 os << path[i];
740 }
741 return os;
742}
assert(baseType &&"element must be base type")
static ParseResult parseType(Type &result, StringRef name, AsmParser &parser)
Parse a type defined by this dialect.
static std::optional< AppID > parseID(const nlohmann::json &jsonID)
Definition Manifest.cpp:119
AcceleratorConnection::ServiceTable ServiceTable
Definition Manifest.cpp:23
static AppIDPath parseIDPath(const nlohmann::json &jsonIDPath)
Definition Manifest.cpp:136
static AppID parseIDChecked(const nlohmann::json &jsonID)
Definition Manifest.cpp:130
static ServicePortDesc parseServicePort(const nlohmann::json &jsonPort)
Definition Manifest.cpp:143
static llvm::raw_ostream & operator<<(llvm::raw_ostream &os, const bool a)
const std::vector< const Type * > & getTypeTable() const
Get the ordered list of types from the manifest.
Definition Manifest.cpp:84
std::optional< const Type * > getType(Type::ID id) const
Definition Manifest.cpp:101
const Type * parseType(const nlohmann::json &typeJson)
Definition Manifest.cpp:594
auto at(const std::string &key) const
Definition Manifest.cpp:37
void populateTypes(const nlohmann::json &typesJson)
Parse all the types and populate the types table.
Definition Manifest.cpp:598
std::optional< ModuleInfo > getModInfo(const nlohmann::json &) const
Definition Manifest.cpp:294
std::vector< std::unique_ptr< BundlePort > > getBundlePorts(AcceleratorConnection &acc, AppIDPath idPath, const ServiceTable &activeServices, const nlohmann::json &instJson) const
Get the bundle ports for the instance at 'idPath' and specified in 'instJson'.
Definition Manifest.cpp:439
std::vector< std::unique_ptr< Instance > > getChildInstances(AppIDPath idPath, AcceleratorConnection &acc, const ServiceTable &activeServices, const nlohmann::json &instJson) const
Build the set of child instances (recursively) for the module instance description.
Definition Manifest.cpp:326
nlohmann::json manifestJson
Definition Manifest.cpp:110
std::vector< services::Service * > getServices(AppIDPath idPath, AcceleratorConnection &, const nlohmann::json &, ServiceTable &activeServices) const
Get all the services in the description of an instance.
Definition Manifest.cpp:425
std::map< std::string, const ModuleInfo > symbolInfoCache
Definition Manifest.cpp:112
const std::map< std::string, const ModuleInfo > & getSymbolInfo() const
Definition Manifest.cpp:93
std::any getAny(const nlohmann::json &value) const
Convert the json value to a 'std::any', which can be exposed outside of this file.
Definition Manifest.cpp:150
void parseModuleMetadata(ModuleInfo &info, const nlohmann::json &mod) const
Definition Manifest.cpp:209
std::unique_ptr< Accelerator > buildAccelerator(AcceleratorConnection &acc) const
Build a dynamic API for the Accelerator connection 'acc' based on the manifest stored herein.
Definition Manifest.cpp:273
void parseModuleConsts(ModuleInfo &info, const nlohmann::json &mod) const
Definition Manifest.cpp:230
services::Service * getService(AppIDPath idPath, AcceleratorConnection &, const nlohmann::json &, ServiceTable &activeServices) const
Get a Service for the service specified in 'json'.
Definition Manifest.cpp:356
void scanServiceDecls(AcceleratorConnection &, const nlohmann::json &, ServiceTable &) const
Go through the "service_decls" section of the manifest and populate the services table as appropriate...
Definition Manifest.cpp:304
Context & ctxt
Definition Manifest.cpp:98
std::vector< const Type * > _typeTable
Definition Manifest.cpp:99
std::unique_ptr< Instance > getChildInstance(AppIDPath idPath, AcceleratorConnection &acc, ServiceTable activeServices, const nlohmann::json &childJson) const
Get a single child instance.
Definition Manifest.cpp:339
Impl(int port)
Start a server on the given port. -1 means to let the OS pick a port.
Definition esi.py:1
std::string name
Definition Common.h:35
std::optional< uint32_t > idx
Definition Common.h:36