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(AcceleratorConnection &conn, TraceAccelerator::Impl &impl)
230 : Engine(conn), impl(impl) {}
231
232 std::unique_ptr<ChannelPort> createPort(AppIDPath idPath,
233 const std::string &channelName,
235 const Type *type) override {
236 std::unique_ptr<ChannelPort> port;
237 if (BundlePort::isWrite(dir))
238 port = std::make_unique<WriteTraceChannelPort>(impl, type, idPath,
239 channelName);
240 else
241 port = std::make_unique<ReadTraceChannelPort>(impl, type);
242 return port;
243 }
244
245private:
247};
248} // namespace
249
250void TraceAccelerator::createEngine(const std::string &dmaEngineName,
251 AppIDPath idPath,
252 const ServiceImplDetails &details,
253 const HWClientDetails &clients) {
254 registerEngine(idPath, std::make_unique<TraceEngine>(*this, getImpl()),
255 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:42
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:250
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: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: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: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