CIRCT 20.0.0git
Loading...
Searching...
No Matches
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
27using namespace esi;
28using namespace esi::services;
29using namespace esi::backends::trace;
30
31// We only support v0.
32constexpr uint32_t ESIVersion = 0;
33
34namespace {
35class TraceChannelPort;
36class TraceEngine;
37} // namespace
38
40
42 friend class TraceAccelerator;
43 Impl(Mode mode, std::filesystem::path manifestJson,
44 std::filesystem::path traceFile)
46 engine = std::make_unique<TraceEngine>(*this);
47 if (!std::filesystem::exists(manifestJson))
48 throw std::runtime_error("manifest file '" + manifestJson.string() +
49 "' does not exist");
50
51 if (mode == Write) {
52 // Open the trace file for writing.
53 traceWrite = new std::ofstream(traceFile);
54 if (!traceWrite->is_open())
55 throw std::runtime_error("failed to open trace file '" +
56 traceFile.string() + "'");
57 } else if (mode == Discard) {
58 traceWrite = nullptr;
59 } else {
60 assert(false && "not implemented");
61 }
62 }
63
65 if (traceWrite) {
66 traceWrite->close();
67 delete traceWrite;
68 }
69 }
70
72 AppIDPath idPath, const ServiceImplDetails &details,
73 const HWClientDetails &clients);
74
75 void adoptChannelPort(ChannelPort *port) { channels.emplace_back(port); }
76
77 void write(const AppIDPath &id, const std::string &portName, const void *data,
78 size_t size, const std::string &prefix = "");
79 std::ostream &write(std::string service) {
80 assert(traceWrite && "traceWrite is null");
81 *traceWrite << "[" << service << "] ";
82 return *traceWrite;
83 }
84 bool isWriteable() { return traceWrite; }
85
86private:
87 std::ofstream *traceWrite;
88 std::filesystem::path manifestJson;
89 std::filesystem::path traceFile;
90 std::vector<std::unique_ptr<ChannelPort>> channels;
91 std::unique_ptr<TraceEngine> engine;
92};
93
94void TraceAccelerator::Impl::write(const AppIDPath &id,
95 const std::string &portName,
96 const void *data, size_t size,
97 const std::string &prefix) {
98 if (!isWriteable())
99 return;
100 std::string b64data;
101 utils::encodeBase64(data, size, b64data);
102
103 *traceWrite << prefix << (prefix.empty() ? "w" : "W") << "rite " << id << '.'
104 << portName << ": " << b64data << std::endl;
105}
106
107std::unique_ptr<AcceleratorConnection>
108TraceAccelerator::connect(Context &ctxt, std::string connectionString) {
109 std::string modeStr;
110 std::string manifestPath;
111 std::string traceFile = "trace.log";
112
113 // Parse the connection std::string.
114 // <mode>:<manifest path>[:<traceFile>]
115 std::regex connPattern("([\\w-]):([^:]+)(:(\\w+))?");
116 std::smatch match;
117 if (regex_search(connectionString, match, connPattern)) {
118 modeStr = match[1];
119 manifestPath = match[2];
120 if (match[3].matched)
121 traceFile = match[3];
122 } else {
123 throw std::runtime_error("connection std::string must be of the form "
124 "'<mode>:<manifest path>[:<traceFile>]'");
125 }
126
127 // Parse the mode.
128 Mode mode;
129 if (modeStr == "w")
130 mode = Write;
131 else if (modeStr == "-")
132 mode = Discard;
133 else
134 throw std::runtime_error("unknown mode '" + modeStr + "'");
135
136 return std::make_unique<TraceAccelerator>(ctxt, mode,
137 std::filesystem::path(manifestPath),
138 std::filesystem::path(traceFile));
139}
140
142 std::filesystem::path manifestJson,
143 std::filesystem::path traceFile)
145 impl = std::make_unique<Impl>(mode, manifestJson, traceFile);
146}
148
149namespace {
150class TraceSysInfo : public SysInfo {
151public:
152 TraceSysInfo(AcceleratorConnection &conn, std::filesystem::path manifestJson)
153 : SysInfo(conn), manifestJson(manifestJson) {}
154
155 uint32_t getEsiVersion() const override { return ESIVersion; }
156
157 std::string getJsonManifest() const override {
158 // Read in the whole json file and return it.
159 std::ifstream manifest(manifestJson);
160 if (!manifest.is_open())
161 throw std::runtime_error("failed to open manifest file '" +
162 manifestJson.string() + "'");
163 std::stringstream buffer;
164 buffer << manifest.rdbuf();
165 manifest.close();
166 return buffer.str();
167 }
168
169 std::vector<uint8_t> getCompressedManifest() const override {
170 throw std::runtime_error(
171 "compressed manifest not supported by trace backend");
172 }
173
174private:
175 std::filesystem::path manifestJson;
176};
177} // namespace
178
179namespace {
180class WriteTraceChannelPort : public WriteChannelPort {
181public:
182 WriteTraceChannelPort(TraceAccelerator::Impl &impl, const Type *type,
183 const AppIDPath &id, const std::string &portName)
184 : WriteChannelPort(type), impl(impl), id(id), portName(portName) {}
185
186 virtual void write(const MessageData &data) override {
187 impl.write(id, portName, data.getBytes(), data.getSize());
188 }
189
190 bool tryWrite(const MessageData &data) override {
191 impl.write(id, portName, data.getBytes(), data.getSize(), "try");
192 return true;
193 }
194
195protected:
197 AppIDPath id;
198 std::string portName;
199};
200} // namespace
201
202namespace {
203class ReadTraceChannelPort : public ReadChannelPort {
204public:
205 ReadTraceChannelPort(TraceAccelerator::Impl &impl, const Type *type)
206 : ReadChannelPort(type) {}
207 ~ReadTraceChannelPort() { disconnect(); }
208
209private:
210 MessageData genMessage() {
211 std::ptrdiff_t numBits = getType()->getBitWidth();
212 if (numBits < 0)
213 // TODO: support other types.
214 throw std::runtime_error("unsupported type for read: " +
215 getType()->getID());
216
217 std::ptrdiff_t size = (numBits + 7) / 8;
218 std::vector<uint8_t> bytes(size);
219 for (std::ptrdiff_t i = 0; i < size; ++i)
220 bytes[i] = rand() % 256;
221 return MessageData(bytes);
222 }
223
224 bool pollImpl() override { return callback(genMessage()); }
225};
226} // namespace
227
228namespace {
229class TraceEngine : public Engine {
230public:
231 TraceEngine(TraceAccelerator::Impl &impl) : impl(impl) {}
232
233 std::unique_ptr<ChannelPort> createPort(AppIDPath idPath,
234 const std::string &channelName,
236 const Type *type) override {
237 std::unique_ptr<ChannelPort> port;
238 if (BundlePort::isWrite(dir))
239 port = std::make_unique<WriteTraceChannelPort>(impl, type, idPath,
240 channelName);
241 else
242 port = std::make_unique<ReadTraceChannelPort>(impl, type);
243 return port;
244 }
245
246private:
248};
249} // namespace
250
251void TraceAccelerator::createEngine(const std::string &dmaEngineName,
252 AppIDPath idPath,
253 const ServiceImplDetails &details,
254 const HWClientDetails &clients) {
255 registerEngine(idPath, std::make_unique<TraceEngine>(getImpl()), clients);
256}
257
258class TraceMMIO : public MMIO {
259public:
261 : MMIO(conn, clients), impl(conn.getImpl()) {}
262
263 virtual uint64_t read(uint32_t addr) const override {
264 uint64_t data = rand();
265 if (impl.isWriteable())
266 impl.write("MMIO") << "[" << std::hex << addr << "] -> " << data
267 << std::endl;
268 return data;
269 }
270 virtual void write(uint32_t addr, uint64_t data) override {
271 if (!impl.isWriteable())
272 return;
273 impl.write("MMIO") << "[" << std::hex << addr << "] <- " << data
274 << std::endl;
275 }
276
277private:
279};
280
281class TraceHostMem : public HostMem {
282public:
283 TraceHostMem(TraceAccelerator &conn) : HostMem(conn), impl(conn.getImpl()) {}
284
287 : impl(impl) {
288 ptr = malloc(size);
289 this->size = size;
290 }
292 if (impl.isWriteable())
293 impl.write("HostMem") << "free " << ptr << std::endl;
294 free(ptr);
295 }
296 virtual void *getPtr() const override { return ptr; }
297 virtual std::size_t getSize() const override { return size; }
298
299 private:
300 void *ptr;
301 std::size_t size;
303 };
304
305 virtual std::unique_ptr<HostMemRegion>
306 allocate(std::size_t size, HostMem::Options opts) const override {
307 auto ret =
308 std::unique_ptr<HostMemRegion>(new TraceHostMemRegion(size, impl));
309 if (impl.isWriteable())
310 impl.write("HostMem 0x")
311 << ret->getPtr() << " allocate " << size
312 << " bytes. Writeable: " << opts.writeable
313 << ", useLargePages: " << opts.useLargePages << std::endl;
314 return ret;
315 }
316 virtual bool mapMemory(void *ptr, std::size_t size,
317 HostMem::Options opts) const override {
318
319 if (impl.isWriteable())
320 impl.write("HostMem")
321 << "map 0x" << ptr << " size " << size
322 << " bytes. Writeable: " << opts.writeable
323 << ", useLargePages: " << opts.useLargePages << std::endl;
324 return true;
325 }
326 virtual void unmapMemory(void *ptr) const override {
327 if (impl.isWriteable())
328 impl.write("HostMem") << "unmap 0x" << ptr << std::endl;
329 }
330
331private:
333};
334
336 AppIDPath idPath, std::string implName,
337 const ServiceImplDetails &details,
338 const HWClientDetails &clients) {
339 if (svcType == typeid(SysInfo))
340 return new TraceSysInfo(*this, getImpl().manifestJson);
341 if (svcType == typeid(MMIO))
342 return new TraceMMIO(*this, clients);
343 if (svcType == typeid(HostMem))
344 return new TraceHostMem(*this);
345 return nullptr;
346}
347
#define REGISTER_ACCELERATOR(Name, TAccelerator)
assert(baseType &&"element must be base type")
constexpr uint32_t ESIVersion
Definition Trace.cpp:32
virtual std::unique_ptr< HostMemRegion > allocate(std::size_t size, HostMem::Options opts) const override
Allocate a region of host memory in accelerator accessible address space.
Definition Trace.cpp:306
TraceHostMem(TraceAccelerator &conn)
Definition Trace.cpp:283
virtual bool mapMemory(void *ptr, std::size_t size, HostMem::Options opts) const override
Try to make a region of host memory accessible to the accelerator.
Definition Trace.cpp:316
virtual void unmapMemory(void *ptr) const override
Unmap memory which was previously mapped with 'mapMemory'.
Definition Trace.cpp:326
TraceAccelerator::Impl & impl
Definition Trace.cpp:332
virtual uint64_t read(uint32_t addr) const override
Read a 64-bit value from the global MMIO space.
Definition Trace.cpp:263
virtual void write(uint32_t addr, uint64_t data) override
Write a 64-bit value to the global MMIO space.
Definition Trace.cpp:270
TraceAccelerator::Impl & impl
Definition Trace.cpp:278
TraceMMIO(TraceAccelerator &conn, const HWClientDetails &clients)
Definition Trace.cpp:260
Abstract class representing a connection to an accelerator.
Definition Accelerator.h:79
virtual void disconnect()
Disconnect from the accelerator cleanly.
Context & ctxt
ESI accelerator context.
void registerEngine(AppIDPath idPath, std::unique_ptr< Engine > engine, const HWClientDetails &clients)
If createEngine is overridden, this method should be called to register the engine and all of the cha...
Unidirectional channels are the basic communication primitive between the host and accelerator.
Definition Ports.h:36
AcceleratorConnections, Accelerators, and Manifests must all share a context.
Definition Context.h:31
Engines implement the actual channel communication between the host and the accelerator.
Definition Engines.h:41
A logical chunk of data representing serialized data.
Definition Common.h:103
A ChannelPort which reads data from the accelerator.
Definition Ports.h:106
Root class of the ESI type system.
Definition Types.h:27
A ChannelPort which sends data to the accelerator.
Definition Ports.h:77
Connect to an ESI simulation.
Definition Trace.h:35
std::unique_ptr< Impl > impl
Definition Trace.h:80
TraceAccelerator(Context &, Mode mode, std::filesystem::path manifestJson, std::filesystem::path traceFile)
Create a trace-based accelerator backend.
Definition Trace.cpp:141
void createEngine(const std::string &engineTypeName, AppIDPath idPath, const ServiceImplDetails &details, const HWClientDetails &clients) override
Create a new engine for channel communication with the accelerator.
Definition Trace.cpp:251
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:335
static std::unique_ptr< AcceleratorConnection > connect(Context &, std::string connectionString)
Parse the connection string and instantiate the accelerator.
Definition Trace.cpp:108
Parent class of all APIs modeled as 'services'.
Definition Services.h:46
const std::type_info & Type
Definition Services.h:48
Information about the Accelerator system.
Definition Services.h:100
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:98
std::vector< HWClientDetail > HWClientDetails
Definition Common.h:97
virtual std::size_t getSize() const override
Definition Trace.cpp:297
TraceHostMemRegion(std::size_t size, TraceAccelerator::Impl &impl)
Definition Trace.cpp:286
virtual void * getPtr() const override
Get a pointer to the host memory.
Definition Trace.cpp:296
TraceAccelerator::Impl & impl
Definition Trace.cpp:302
void write(const AppIDPath &id, const std::string &portName, const void *data, size_t size, const std::string &prefix="")
Definition Trace.cpp:94
std::vector< std::unique_ptr< ChannelPort > > channels
Definition Trace.cpp:90
std::ostream & write(std::string service)
Definition Trace.cpp:79
void adoptChannelPort(ChannelPort *port)
Definition Trace.cpp:75
Service * createService(TraceAccelerator &conn, Service::Type svcType, AppIDPath idPath, const ServiceImplDetails &details, const HWClientDetails &clients)
Impl(Mode mode, std::filesystem::path manifestJson, std::filesystem::path traceFile)
Definition Trace.cpp:43
std::unique_ptr< TraceEngine > engine
Definition Trace.cpp:91
RAII memory region for host memory.
Definition Services.h:208
Options for allocating host memory.
Definition Services.h:226