CIRCT  19.0.0git
Trace.cpp
Go to the documentation of this file.
1 //===- Trace.cpp - Implementation of trace backend -----------------------===//
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/lib/).
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "esi/backends/Trace.h"
16 
17 #include "esi/Accelerator.h"
18 #include "esi/Services.h"
19 #include "esi/Utils.h"
20 
21 #include <cassert>
22 #include <fstream>
23 #include <iostream>
24 #include <regex>
25 #include <sstream>
26 
27 using namespace std;
28 
29 using namespace esi;
30 using namespace esi::services;
31 using namespace esi::backends::trace;
32 
33 // We only support v1.
34 constexpr uint32_t ESIVersion = 1;
35 
36 namespace {
37 class TraceChannelPort;
38 }
39 
41  Impl(Mode mode, filesystem::path manifestJson, filesystem::path traceFile)
42  : manifestJson(manifestJson), traceFile(traceFile) {
43  if (!filesystem::exists(manifestJson))
44  throw runtime_error("manifest file '" + manifestJson.string() +
45  "' does not exist");
46 
47  if (mode == Write) {
48  // Open the trace file for writing.
49  traceWrite = new ofstream(traceFile);
50  if (!traceWrite->is_open())
51  throw runtime_error("failed to open trace file '" + traceFile.string() +
52  "'");
53  } else {
54  assert(false && "not implemented");
55  }
56  }
57 
58  ~Impl() {
59  if (traceWrite) {
60  traceWrite->close();
61  delete traceWrite;
62  }
63  }
64 
65  Service *createService(Service::Type svcType, AppIDPath idPath,
66  const ServiceImplDetails &details,
67  const HWClientDetails &clients);
68 
69  /// Request the host side channel ports for a particular instance (identified
70  /// by the AppID path). For convenience, provide the bundle type and direction
71  /// of the bundle port.
72  std::map<std::string, ChannelPort &> requestChannelsFor(AppIDPath,
73  const BundleType *);
74 
75  void adoptChannelPort(ChannelPort *port) { channels.emplace_back(port); }
76 
77  void write(const AppIDPath &id, const string &portName, const void *data,
78  size_t size);
79 
80 private:
81  ofstream *traceWrite;
82  filesystem::path manifestJson;
83  filesystem::path traceFile;
84  vector<unique_ptr<ChannelPort>> channels;
85 };
86 
87 void TraceAccelerator::Impl::write(const AppIDPath &id, const string &portName,
88  const void *data, size_t size) {
89  string b64data;
90  utils::encodeBase64(data, size, b64data);
91 
92  *traceWrite << "write " << id << '.' << portName << ": " << b64data << endl;
93 }
94 
95 unique_ptr<AcceleratorConnection>
96 TraceAccelerator::connect(Context &ctxt, string connectionString) {
97  string modeStr;
98  string manifestPath;
99  string traceFile = "trace.log";
100 
101  // Parse the connection string.
102  // <mode>:<manifest path>[:<traceFile>]
103  regex connPattern("(\\w):([^:]+)(:(\\w+))?");
104  smatch match;
105  if (regex_search(connectionString, match, connPattern)) {
106  modeStr = match[1];
107  manifestPath = match[2];
108  if (match[3].matched)
109  traceFile = match[3];
110  } else {
111  throw runtime_error("connection string must be of the form "
112  "'<mode>:<manifest path>[:<traceFile>]'");
113  }
114 
115  // Parse the mode.
116  Mode mode;
117  if (modeStr == "w")
118  mode = Write;
119  else
120  throw runtime_error("unknown mode '" + modeStr + "'");
121 
122  return make_unique<TraceAccelerator>(
123  ctxt, mode, filesystem::path(manifestPath), filesystem::path(traceFile));
124 }
125 
126 TraceAccelerator::TraceAccelerator(Context &ctxt, Mode mode,
127  filesystem::path manifestJson,
128  filesystem::path traceFile)
130  impl = make_unique<Impl>(mode, manifestJson, traceFile);
131 }
132 
134  AppIDPath idPath, std::string implName,
135  const ServiceImplDetails &details,
136  const HWClientDetails &clients) {
137  return impl->createService(svcType, idPath, details, clients);
138 }
139 namespace {
140 class TraceSysInfo : public SysInfo {
141 public:
142  TraceSysInfo(filesystem::path manifestJson) : manifestJson(manifestJson) {}
143 
144  uint32_t getEsiVersion() const override { return ESIVersion; }
145 
146  string getJsonManifest() const override {
147  // Read in the whole json file and return it.
148  ifstream manifest(manifestJson);
149  if (!manifest.is_open())
150  throw runtime_error("failed to open manifest file '" +
151  manifestJson.string() + "'");
152  stringstream buffer;
153  buffer << manifest.rdbuf();
154  manifest.close();
155  return buffer.str();
156  }
157 
158  vector<uint8_t> getCompressedManifest() const override {
159  throw runtime_error("compressed manifest not supported by trace backend");
160  }
161 
162 private:
163  filesystem::path manifestJson;
164 };
165 } // namespace
166 
167 namespace {
168 class WriteTraceChannelPort : public WriteChannelPort {
169 public:
170  WriteTraceChannelPort(TraceAccelerator::Impl &impl, const Type *type,
171  const AppIDPath &id, const string &portName)
172  : WriteChannelPort(type), impl(impl), id(id), portName(portName) {}
173 
174  virtual void write(const MessageData &data) override {
175  impl.write(id, portName, data.getBytes(), data.getSize());
176  }
177 
178 protected:
180  AppIDPath id;
181  string portName;
182 };
183 } // namespace
184 
185 namespace {
186 class ReadTraceChannelPort : public ReadChannelPort {
187 public:
188  ReadTraceChannelPort(TraceAccelerator::Impl &impl, const Type *type)
189  : ReadChannelPort(type) {}
190 
191  virtual bool read(MessageData &data) override;
192 
193 private:
194  size_t numReads = 0;
195 };
196 } // namespace
197 
198 bool ReadTraceChannelPort::read(MessageData &data) {
199  if ((++numReads & 0x1) == 1)
200  return false;
201 
202  std::ptrdiff_t numBits = getType()->getBitWidth();
203  if (numBits < 0)
204  // TODO: support other types.
205  throw runtime_error("unsupported type for read: " + getType()->getID());
206 
207  std::ptrdiff_t size = (numBits + 7) / 8;
208  std::vector<uint8_t> bytes(size);
209  for (std::ptrdiff_t i = 0; i < size; ++i)
210  bytes[i] = rand() % 256;
211  data = MessageData(bytes);
212  return true;
213 }
214 
215 namespace {
216 class TraceCustomService : public CustomService {
217 public:
218  TraceCustomService(TraceAccelerator::Impl &impl, AppIDPath idPath,
219  const ServiceImplDetails &details,
220  const HWClientDetails &clients)
221  : CustomService(idPath, details, clients) {}
222 };
223 } // namespace
224 
225 map<string, ChannelPort &>
227  const BundleType *bundleType) {
228  map<string, ChannelPort &> channels;
229  for (auto [name, dir, type] : bundleType->getChannels()) {
230  ChannelPort *port;
231  if (BundlePort::isWrite(dir))
232  port = new WriteTraceChannelPort(*this, type, idPath, name);
233  else
234  port = new ReadTraceChannelPort(*this, type);
235  channels.emplace(name, *port);
236  adoptChannelPort(port);
237  }
238  return channels;
239 }
240 
241 map<string, ChannelPort &>
243  const BundleType *bundleType) {
244  return impl->requestChannelsFor(idPath, bundleType);
245 }
246 
247 Service *
249  const ServiceImplDetails &details,
250  const HWClientDetails &clients) {
251  if (svcType == typeid(SysInfo))
252  return new TraceSysInfo(manifestJson);
253  if (svcType == typeid(CustomService))
254  return new TraceCustomService(*this, idPath, details, clients);
255  return nullptr;
256 }
257 
assert(baseType &&"element must be base type")
constexpr uint32_t ESIVersion
Definition: Trace.cpp:34
REGISTER_ACCELERATOR("trace", TraceAccelerator)
Abstract class representing a connection to an accelerator.
Definition: Accelerator.h:75
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:78
Bundles represent a collection of channels.
Definition: Types.h:44
const ChannelVector & getChannels() const
Definition: Types.h:54
Unidirectional channels are the basic communication primitive between the host and accelerator.
Definition: Ports.h:31
AcceleratorConnections, Accelerators, and Manifests must all share a context.
Definition: Context.h:30
A logical chunk of data representing serialized data.
Definition: Common.h:85
A ChannelPort which reads data from the accelerator.
Definition: Ports.h:55
Root class of the ESI type system.
Definition: Types.h:27
A ChannelPort which sends data to the accelerator.
Definition: Ports.h:46
Connect to an ESI simulation.
Definition: Trace.h:35
std::unique_ptr< Impl > impl
Definition: Trace.h:76
std::map< std::string, ChannelPort & > requestChannelsFor(AppIDPath, const BundleType *) override
Request the host side channel ports for a particular instance (identified by the AppID path).
Definition: Trace.cpp:242
virtual Service * createService(Service::Type service, AppIDPath idPath, std::string implName, const ServiceImplDetails &details, const HWClientDetails &clients) override
Called by getServiceImpl exclusively.
Definition: Trace.cpp:133
A service for which there are no standard services registered.
Definition: Services.h:61
Parent class of all APIs modeled as 'services'.
Definition: Services.h:42
const std::type_info & Type
Definition: Services.h:44
Information about the Accelerator system.
Definition: Services.h:77
def connect(destination, source)
Definition: support.py:37
void encodeBase64(const void *data, size_t size, std::string &out)
Definition: Utils.cpp:23
Definition: esi.py:1
std::map< std::string, std::any > ServiceImplDetails
Definition: Common.h:80
std::vector< HWClientDetail > HWClientDetails
Definition: Common.h:79
Service * createService(Service::Type svcType, AppIDPath idPath, const ServiceImplDetails &details, const HWClientDetails &clients)
Definition: Trace.cpp:248
vector< unique_ptr< ChannelPort > > channels
Definition: Trace.cpp:84
std::map< std::string, ChannelPort & > requestChannelsFor(AppIDPath, const BundleType *)
Request the host side channel ports for a particular instance (identified by the AppID path).
Definition: Trace.cpp:226
Impl(Mode mode, filesystem::path manifestJson, filesystem::path traceFile)
Definition: Trace.cpp:41
void adoptChannelPort(ChannelPort *port)
Definition: Trace.cpp:75