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