CIRCT 22.0.0git
Loading...
Searching...
No Matches
esiquery.cpp
Go to the documentation of this file.
1//===- esiquery.cpp - ESI accelerator system query tool -------------------===//
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/Accelerator.h"
17#include "esi/CLI.h"
18#include "esi/Manifest.h"
19#include "esi/Services.h"
20
21#include <algorithm>
22#include <iostream>
23#include <map>
24#if defined(__GNUC__)
25#pragma GCC diagnostic push
26#pragma GCC diagnostic ignored "-Wcovered-switch-default"
27#endif
28#include <nlohmann/json.hpp>
29#if defined(__GNUC__)
30#pragma GCC diagnostic pop
31#endif
32#include <stdexcept>
33#include <string>
34
35using namespace esi;
36
37void printInfo(std::ostream &os, AcceleratorConnection &acc, bool details);
38void printHier(std::ostream &os, AcceleratorConnection &acc, bool details);
39void printTelemetry(std::ostream &os, AcceleratorConnection &acc);
40void printTelemetryJson(std::ostream &os, AcceleratorConnection &acc);
41
42int main(int argc, const char *argv[]) {
43 CliParser cli("esiquery");
44 cli.description("Query an ESI system for information from the manifest.");
45
46 CLI::App *versionSub =
47 cli.add_subcommand("version", "Print ESI system version");
48 bool infoDetails = false;
49 CLI::App *infoSub =
50 cli.add_subcommand("info", "Print ESI system information");
51 infoSub->add_flag("--details", infoDetails,
52 "Print detailed information about the system");
53 bool hierDetails = false;
54 CLI::App *hierSub = cli.add_subcommand("hier", "Print ESI system hierarchy");
55 hierSub->add_flag("--details", hierDetails,
56 "Print detailed information about the system");
57 bool telemetryJson = false;
58 CLI::App *telemetrySub =
59 cli.add_subcommand("telemetry", "Print ESI system telemetry information");
60 telemetrySub->add_flag("--json", telemetryJson,
61 "Dump telemetry information as JSON");
62
63 if (int rc = cli.esiParse(argc, argv))
64 return rc;
65 if (!cli.get_help_ptr()->empty())
66 return 0;
67
68 Context &ctxt = cli.getContext();
69 try {
70 AcceleratorConnection *acc = cli.connect();
71 const auto &info = *acc->getService<services::SysInfo>();
72
73 if (*versionSub)
74 std::cout << info.getEsiVersion() << std::endl;
75 else if (*infoSub)
76 printInfo(std::cout, *acc, infoDetails);
77 else if (*hierSub)
78 printHier(std::cout, *acc, hierDetails);
79 else if (*telemetrySub) {
80 if (telemetryJson)
81 printTelemetryJson(std::cout, *acc);
82 else
83 printTelemetry(std::cout, *acc);
84 }
85 return 0;
86 } catch (std::exception &e) {
87 ctxt.getLogger().error("esiquery", e.what());
88 return -1;
89 }
90}
91
92void printInfo(std::ostream &os, AcceleratorConnection &acc, bool details) {
93 std::string jsonManifest =
94 acc.getService<services::SysInfo>()->getJsonManifest();
95 Manifest m(acc.getCtxt(), jsonManifest);
96 os << "API version: " << m.getApiVersion() << std::endl << std::endl;
97 os << "********************************" << std::endl;
98 os << "* Module information" << std::endl;
99 os << "********************************" << std::endl;
100 os << std::endl;
101 for (ModuleInfo mod : m.getModuleInfos())
102 os << "- " << mod;
103
104 if (!details)
105 return;
106
107 os << std::endl;
108 os << "********************************" << std::endl;
109 os << "* Type table" << std::endl;
110 os << "********************************" << std::endl;
111 os << std::endl;
112 size_t i = 0;
113 for (const Type *t : m.getTypeTable())
114 os << " " << i++ << ": " << t->getID() << std::endl;
115}
116
117static bool showPort(const BundlePort &port, bool details) {
118 return details ||
119 (!port.getID().name.starts_with("__") && !port.getChannels().empty());
120}
121
122void printPort(std::ostream &os, const BundlePort &port, std::string indent,
123 bool details) {
124 if (!showPort(port, details))
125 return;
126 os << indent << " " << port.getID() << ":";
127 if (auto svcPort = dynamic_cast<const services::ServicePort *>(&port))
128 if (auto svcPortStr = svcPort->toString(true)) {
129 os << " " << *svcPortStr << std::endl;
130 return;
131 }
132 os << std::endl;
133 for (const auto &[name, chan] : port.getChannels())
134 os << indent << " " << name << ": " << chan.getType()->toString(true)
135 << std::endl;
136}
137
138void printInstance(std::ostream &os, const HWModule *d, std::string indent,
139 bool details) {
140 bool hasPorts =
141 std::any_of(d->getPorts().begin(), d->getPorts().end(),
142 [&](const std::pair<const AppID, BundlePort &> port) {
143 return showPort(port.second, details);
144 });
145 if (!details && !hasPorts && d->getChildren().empty())
146 return;
147 os << indent << "* Instance: ";
148 if (auto inst = dynamic_cast<const Instance *>(d)) {
149 os << inst->getID() << std::endl;
150 if (inst->getInfo() && inst->getInfo()->name)
151 os << indent << "* Module: " << *inst->getInfo()->name << std::endl;
152 } else {
153 os << "top" << std::endl;
154 }
155
156 os << indent << "* Ports:" << std::endl;
157 for (const BundlePort &port : d->getPortsOrdered())
158 printPort(os, port, indent + " ", details);
159 std::vector<const Instance *> children = d->getChildrenOrdered();
160 if (!children.empty()) {
161 os << indent << "* Children:" << std::endl;
162 for (const Instance *child : d->getChildrenOrdered())
163 printInstance(os, child, indent + " ", details);
164 }
165 os << std::endl;
166}
167
168void printHier(std::ostream &os, AcceleratorConnection &acc, bool details) {
169 Manifest manifest(acc.getCtxt(),
171 Accelerator *design = manifest.buildAccelerator(acc);
172 os << "********************************" << std::endl;
173 os << "* Design hierarchy" << std::endl;
174 os << "********************************" << std::endl;
175 os << std::endl;
176 printInstance(os, design, /*indent=*/"", details);
177}
178
179// Recursively collect telemetry metrics into a hierarchical JSON structure.
180static bool collectTelemetryJson(const HWModule &module, nlohmann::json &node) {
181 bool hasData = false;
182
183 for (const auto &portRef : module.getPortsOrdered()) {
184 BundlePort &port = portRef.get();
185 if (auto *metric =
186 dynamic_cast<services::TelemetryService::Metric *>(&port)) {
187 metric->connect();
188 node[metric->getID().toString()] = metric->readInt();
189 hasData = true;
190 }
191 }
192
193 for (const Instance *child : module.getChildrenOrdered()) {
194 nlohmann::json childNode = nlohmann::json::object();
195 if (collectTelemetryJson(*child, childNode)) {
196 node[child->getID().toString()] = childNode;
197 hasData = true;
198 }
199 }
200
201 return hasData;
202}
203
204void printTelemetryJson(std::ostream &os, AcceleratorConnection &acc) {
205 Manifest manifest(acc.getCtxt(),
207 auto accel = manifest.buildAccelerator(acc);
208 acc.getServiceThread()->addPoll(*accel);
209
210 nlohmann::json root = nlohmann::json::object();
211 if (!collectTelemetryJson(*accel, root))
212 root = nlohmann::json{{"error", "No telemetry metrics found"}};
213
214 os << root.dump(2) << std::endl;
215}
216
217void printTelemetry(std::ostream &os, AcceleratorConnection &acc) {
218 Manifest manifest(acc.getCtxt(),
220 auto accel = manifest.buildAccelerator(acc);
221 acc.getServiceThread()->addPoll(*accel);
222
223 auto *telemetry = acc.getService<services::TelemetryService>();
224 if (!telemetry) {
225 os << "No telemetry service found" << std::endl;
226 return;
227 }
228 os << "********************************" << std::endl;
229 os << "* Telemetry" << std::endl;
230 os << "********************************" << std::endl;
231 os << std::endl;
232
233 const std::map<AppIDPath, services::TelemetryService::Metric *>
234 &telemetryPorts = telemetry->getTelemetryPorts();
235 for (const auto &[id, port] : telemetryPorts) {
236 port->connect();
237 os << id << ": ";
238 os.flush();
239 uint64_t value = port->readInt();
240 os << value << std::endl;
241 }
242}
Abstract class representing a connection to an accelerator.
Definition Accelerator.h:79
ServiceClass * getService(AppIDPath id={}, std::string implName={}, ServiceImplDetails details={}, HWClientDetails clients={})
Get a typed reference to a particular service type.
Context & getCtxt() const
Definition Accelerator.h:83
AcceleratorServiceThread * getServiceThread()
Return a pointer to the accelerator 'service' thread (or threads).
void addPoll(HWModule &module)
Poll this module.
Top level accelerator class.
Definition Accelerator.h:60
Services provide connections to 'bundles' – collections of named, unidirectional communication channe...
Definition Ports.h:433
const PortMap & getChannels() const
Definition Ports.h:454
AppID getID() const
Get the ID of the port.
Definition Ports.h:446
Common options and code for ESI runtime tools.
Definition CLI.h:29
Context & getContext()
Get the context.
Definition CLI.h:63
AcceleratorConnection * connect()
Connect to the accelerator using the specified backend and connection.
Definition CLI.h:60
int esiParse(int argc, const char **argv)
Run the parser.
Definition CLI.h:46
AcceleratorConnections, Accelerators, and Manifests must all share a context.
Definition Context.h:34
Logger & getLogger()
Definition Context.h:69
Represents either the top level or an instance of a hardware module.
Definition Design.h:47
std::vector< std::reference_wrapper< BundlePort > > getPortsOrdered() const
Get the module's ports in a deterministic order.
Definition Design.h:73
std::vector< const Instance * > getChildrenOrdered() const
Get a vector of the module's children in a deterministic order.
Definition Design.h:64
const std::map< AppID, BundlePort & > & getPorts() const
Access the module's ports by ID.
Definition Design.h:80
const std::map< AppID, Instance * > & getChildren() const
Access the module's children by ID.
Definition Design.h:71
Subclass of HWModule which represents a submodule instance.
Definition Design.h:111
virtual void error(const std::string &subsystem, const std::string &msg, const std::map< std::string, std::any > *details=nullptr)
Report an error.
Definition Logging.h:64
Class to parse a manifest.
Definition Manifest.h:39
uint32_t getApiVersion() const
Accelerator * buildAccelerator(AcceleratorConnection &acc) const
const std::vector< const Type * > & getTypeTable() const
The Type Table is an ordered list of types.
std::vector< ModuleInfo > getModuleInfos() const
Root class of the ESI type system.
Definition Types.h:34
Add a custom interface to a service client at a particular point in the design hierarchy.
Definition Services.h:47
Information about the Accelerator system.
Definition Services.h:113
virtual std::string getJsonManifest() const
Return the JSON-formatted system manifest.
Definition Services.cpp:40
A telemetry port which gets attached to a service port.
Definition Services.h:393
Service for retrieving telemetry data from the accelerator.
Definition Services.h:376
std::map< AppIDPath, Metric * > getTelemetryPorts()
Definition Services.h:418
void printHier(std::ostream &os, AcceleratorConnection &acc, bool details)
Definition esiquery.cpp:168
void printInstance(std::ostream &os, const HWModule *d, std::string indent, bool details)
Definition esiquery.cpp:138
void printPort(std::ostream &os, const BundlePort &port, std::string indent, bool details)
Definition esiquery.cpp:122
void printInfo(std::ostream &os, AcceleratorConnection &acc, bool details)
Definition esiquery.cpp:92
void printTelemetry(std::ostream &os, AcceleratorConnection &acc)
Definition esiquery.cpp:217
static bool showPort(const BundlePort &port, bool details)
Definition esiquery.cpp:117
static bool collectTelemetryJson(const HWModule &module, nlohmann::json &node)
Definition esiquery.cpp:180
int main(int argc, const char *argv[])
Definition esiquery.cpp:42
void printTelemetryJson(std::ostream &os, AcceleratorConnection &acc)
Definition esiquery.cpp:204
Definition esi.py:1
std::string name
Definition Common.h:36
std::string toString() const
Definition Common.h:48