Loading [MathJax]/extensions/tex2jax.js
CIRCT 21.0.0git
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
esitester.cpp
Go to the documentation of this file.
1//===- esitester.cpp - ESI accelerator test/example 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 runtime package. The source for
11// this file should always be modified within CIRCT
12// (lib/dialect/ESI/runtime/cpp/tools/esitester.cpp).
13//
14//===----------------------------------------------------------------------===//
15//
16// This application isn't a utility so much as a test driver for an ESI system.
17// It is also useful as an example of how to use the ESI C++ API. esiquery.cpp
18// is also useful as an example.
19//
20//===----------------------------------------------------------------------===//
21
22#include "esi/Accelerator.h"
23#include "esi/CLI.h"
24#include "esi/Manifest.h"
25#include "esi/Services.h"
26
27#include <chrono>
28#include <iostream>
29#include <map>
30#include <stdexcept>
31
32using namespace esi;
33
35static void hostmemTest(AcceleratorConnection *, Accelerator *, bool read,
36 bool write);
37static void dmaTest(AcceleratorConnection *, Accelerator *, bool read,
38 bool write);
40 uint32_t xferCount,
41 const std::vector<uint32_t> &widths, bool read,
42 bool write);
43
44int main(int argc, const char *argv[]) {
45 CliParser cli("esitester");
46 cli.description("Test an ESI system running the ESI tester image.");
47 cli.require_subcommand(1);
48
49 CLI::App *loopSub = cli.add_subcommand("loop", "Loop indefinitely");
50
51 CLI::App *waitSub =
52 cli.add_subcommand("wait", "Wait for a certain number of seconds");
53 uint32_t waitTime = 1;
54 waitSub->add_option("-t,--time", waitTime, "Number of seconds to wait");
55
56 CLI::App *hostmemtestSub =
57 cli.add_subcommand("hostmem", "Run the host memory test");
58 bool hmRead = false;
59 bool hmWrite = false;
60 hostmemtestSub->add_flag("-w,--write", hmWrite,
61 "Enable host memory write test");
62 hostmemtestSub->add_flag("-r,--read", hmRead, "Enable host memory read test");
63
64 CLI::App *dmatestSub = cli.add_subcommand("dma", "Run the DMA test");
65 bool dmaRead = false;
66 bool dmaWrite = false;
67 dmatestSub->add_flag("-w,--write", dmaWrite, "Enable dma write test");
68 dmatestSub->add_flag("-r,--read", dmaRead, "Enable dma read test");
69
70 CLI::App *bandwidthSub =
71 cli.add_subcommand("bandwidth", "Run the bandwidth test");
72 uint32_t xferCount = 1000;
73 bandwidthSub->add_option("-c,--count", xferCount,
74 "Number of transfers to perform");
75 bool bandwidthRead = false;
76 bool bandwidthWrite = false;
77 std::vector<uint32_t> widths = {32, 64, 128, 256, 384, 504, 512};
78 bandwidthSub->add_option("--widths", widths,
79 "Width of the transfers to perform (default: 32, "
80 "64, 128, 256, 384, 504, 512)");
81 bandwidthSub->add_flag("-w,--write", bandwidthWrite,
82 "Enable bandwidth write");
83 bandwidthSub->add_flag("-r,--read", bandwidthRead, "Enable bandwidth read");
84
85 if (int rc = cli.esiParse(argc, argv))
86 return rc;
87 if (!cli.get_help_ptr()->empty())
88 return 0;
89
90 Context &ctxt = cli.getContext();
91 try {
92 std::unique_ptr<AcceleratorConnection> acc = cli.connect();
93 const auto &info = *acc->getService<services::SysInfo>();
94 Manifest manifest(ctxt, info.getJsonManifest());
95 Accelerator *accel = manifest.buildAccelerator(*acc);
96 acc->getServiceThread()->addPoll(*accel);
97
98 if (*loopSub) {
99 registerCallbacks(acc.get(), accel);
100 while (true) {
101 std::this_thread::sleep_for(std::chrono::milliseconds(100));
102 }
103 } else if (*waitSub) {
104 registerCallbacks(acc.get(), accel);
105 std::this_thread::sleep_for(std::chrono::seconds(waitTime));
106 } else if (*hostmemtestSub) {
107 hostmemTest(acc.get(), accel, hmRead, hmWrite);
108 } else if (*dmatestSub) {
109 dmaTest(acc.get(), accel, dmaRead, dmaWrite);
110 } else if (*bandwidthSub) {
111 bandwidthTest(acc.get(), accel, xferCount, widths, bandwidthRead,
112 bandwidthWrite);
113 }
114
115 acc->disconnect();
116 std::cout << "Exiting successfully\n";
117 return 0;
118 } catch (std::exception &e) {
119 ctxt.getLogger().error("esitester", e.what());
120 return -1;
121 }
122}
123
125 auto ports = accel->getPorts();
126 auto f = ports.find(AppID("PrintfExample"));
127 if (f != ports.end()) {
128 auto callPort = f->second.getAs<services::CallService::Callback>();
129 if (callPort)
130 callPort->connect(
131 [conn](const MessageData &data) -> MessageData {
132 conn->getLogger().debug(
133 [&](std::string &subsystem, std::string &msg,
134 std::unique_ptr<std::map<std::string, std::any>> &details) {
135 subsystem = "ESITESTER";
136 msg = "Received PrintfExample message";
137 details = std::make_unique<std::map<std::string, std::any>>();
138 details->emplace("data", data);
139 });
140 std::cout << "PrintfExample: " << *data.as<uint32_t>() << std::endl;
141 return MessageData();
142 },
143 true);
144 else
145 std::cerr << "PrintfExample port is not a CallService::Callback"
146 << std::endl;
147 } else {
148 std::cerr << "No PrintfExample port found" << std::endl;
149 }
150}
151
152/// Initiate a test read.
154 esi::services::HostMem::HostMemRegion &region, uint32_t width,
155 void *devicePtr, bool read, bool write) {
156 std::cout << "Running hostmem test with width " << width << std::endl;
157 uint64_t *dataPtr = static_cast<uint64_t *>(region.getPtr());
158
159 if (read) {
160 auto readMemChildIter = acc->getChildren().find(AppID("readmem", width));
161 if (readMemChildIter == acc->getChildren().end())
162 throw std::runtime_error("hostmem test failed. No readmem child found");
163 auto &readMemPorts = readMemChildIter->second->getPorts();
164 auto readMemPortIter = readMemPorts.find(AppID("ReadMem"));
165 if (readMemPortIter == readMemPorts.end())
166 throw std::runtime_error("hostmem test failed. No ReadMem port found");
167 auto *readMem = readMemPortIter->second.getAs<services::MMIO::MMIORegion>();
168 if (!readMem)
169 throw std::runtime_error("hostmem test failed. ReadMem port is not MMIO");
170
171 for (size_t i = 0; i < 8; ++i) {
172 dataPtr[0] = 0x12345678 << i;
173 dataPtr[1] = 0xDEADBEEF << i;
174 region.flush();
175 readMem->write(8, reinterpret_cast<uint64_t>(devicePtr));
176
177 // Wait for the accelerator to read the correct value. Timeout and fail
178 // after 10ms.
179 uint64_t val = 0;
180 uint64_t expected = dataPtr[0];
181 if (width < 64)
182 expected &= ((1ull << width) - 1);
183 for (int i = 0; i < 100; ++i) {
184 val = readMem->read(0);
185 if (val == expected)
186 break;
187 std::this_thread::sleep_for(std::chrono::microseconds(100));
188 }
189
190 if (val != expected)
191 throw std::runtime_error("hostmem read test failed. Expected " +
192 esi::toHex(expected) + ", got " +
193 esi::toHex(val));
194 }
195 }
196
197 // Initiate a test write.
198 if (write) {
199 assert(width % 8 == 0);
200 auto check = [&](bool print) {
201 bool ret = true;
202 for (size_t i = 0; i < 8; ++i) {
203 if (print)
204 std::cout << "dataPtr[" << i << "] = 0x" << esi::toHex(dataPtr[i])
205 << std::endl;
206 if (i < (width + 63) / 64 && dataPtr[i] == 0xFFFFFFFFFFFFFFFFull)
207 ret = false;
208 }
209 return ret;
210 };
211
212 auto writeMemChildIter = acc->getChildren().find(AppID("writemem", width));
213 if (writeMemChildIter == acc->getChildren().end())
214 throw std::runtime_error("hostmem test failed. No writemem child found");
215 auto &writeMemPorts = writeMemChildIter->second->getPorts();
216 auto writeMemPortIter = writeMemPorts.find(AppID("WriteMem"));
217 if (writeMemPortIter == writeMemPorts.end())
218 throw std::runtime_error("hostmem test failed. No WriteMem port found");
219 auto *writeMem =
220 writeMemPortIter->second.getAs<services::MMIO::MMIORegion>();
221 if (!writeMem)
222 throw std::runtime_error(
223 "hostmem test failed. WriteMem port is not MMIO");
224
225 for (size_t i = 0, e = 8; i < e; ++i)
226 dataPtr[i] = 0xFFFFFFFFFFFFFFFFull;
227 region.flush();
228
229 // Command the accelerator to write to 'devicePtr', the pointer which the
230 // device should use for 'dataPtr'.
231 writeMem->write(0, reinterpret_cast<uint64_t>(devicePtr));
232 // Wait for the accelerator to write. Timeout and fail after 10ms.
233 for (int i = 0; i < 100; ++i) {
234 if (check(false))
235 break;
236 std::this_thread::sleep_for(std::chrono::microseconds(100));
237 }
238 if (!check(true))
239 throw std::runtime_error("hostmem write test failed");
240
241 // Check that the accelerator didn't write too far.
242 size_t widthInBytes = width / 8;
243 uint8_t *dataPtr8 = reinterpret_cast<uint8_t *>(region.getPtr());
244 for (size_t i = widthInBytes; i < 64; ++i) {
245 std::cout << "endcheck dataPtr8[" << i << "] = 0x"
246 << esi::toHex(dataPtr8[i]) << std::endl;
247 if (dataPtr8[i] != 0xFF)
248 throw std::runtime_error(
249 "hostmem write test failed -- write went too far");
250 }
251 }
252}
253
255 bool write) {
256 // Enable the host memory service.
257 auto hostmem = conn->getService<services::HostMem>();
258 hostmem->start();
259 auto scratchRegion = hostmem->allocate(/*size(bytes)=*/512, /*memOpts=*/{});
260 uint64_t *dataPtr = static_cast<uint64_t *>(scratchRegion->getPtr());
261 for (size_t i = 0; i < scratchRegion->getSize() / 8; ++i)
262 dataPtr[i] = 0;
263 scratchRegion->flush();
264
265 for (size_t width : {32, 64, 128, 256, 384, 504, 512})
266 hostmemTest(acc, *scratchRegion, width, scratchRegion->getDevicePtr(), read,
267 write);
268}
269
271 size_t width) {
272 Logger &logger = conn->getLogger();
273 logger.info("esitester",
274 "== Running DMA read test with width " + std::to_string(width));
275 AppIDPath lastPath;
276 BundlePort *toHostMMIOPort = acc->resolvePort(
277 {AppID("tohostdmatest", width), AppID("ToHostDMATest")}, lastPath);
278 if (!toHostMMIOPort)
279 throw std::runtime_error("dma read test failed. No tohostdmatest[" +
280 std::to_string(width) + "] found");
281 auto *toHostMMIO = toHostMMIOPort->getAs<services::MMIO::MMIORegion>();
282 if (!toHostMMIO)
283 throw std::runtime_error("dma read test failed. MMIO port is not MMIO");
284 lastPath.clear();
285 BundlePort *outPortBundle =
286 acc->resolvePort({AppID("tohostdmatest", width), AppID("out")}, lastPath);
287 ReadChannelPort &outPort = outPortBundle->getRawRead("data");
288 outPort.connect();
289
290 size_t xferCount = 24;
291 uint64_t last = 0;
292 MessageData data;
293 toHostMMIO->write(0, xferCount);
294 for (size_t i = 0; i < xferCount; ++i) {
295 outPort.read(data);
296 if (width == 64) {
297 uint64_t val = *data.as<uint64_t>();
298 if (val < last)
299 throw std::runtime_error("dma read test failed. Out of order data");
300 last = val;
301 }
302 logger.debug("esitester",
303 "Cycle count [" + std::to_string(i) + "] = 0x" + data.toHex());
304 }
305 outPort.disconnect();
306 logger.info("esitester", "== DMA read test complete");
307}
308
310 size_t width) {
311 Logger &logger = conn->getLogger();
312 logger.info("esitester",
313 "== Running DMA write test with width " + std::to_string(width));
314 AppIDPath lastPath;
315 BundlePort *fromHostMMIOPort = acc->resolvePort(
316 {AppID("fromhostdmatest", width), AppID("FromHostDMATest")}, lastPath);
317 if (!fromHostMMIOPort)
318 throw std::runtime_error("dma read test for " + toString(width) +
319 " bits failed. No fromhostdmatest[" +
320 std::to_string(width) + "] found");
321 auto *fromHostMMIO = fromHostMMIOPort->getAs<services::MMIO::MMIORegion>();
322 if (!fromHostMMIO)
323 throw std::runtime_error("dma write test for " + toString(width) +
324 " bits failed. MMIO port is not MMIO");
325 lastPath.clear();
326 BundlePort *outPortBundle = acc->resolvePort(
327 {AppID("fromhostdmatest", width), AppID("in")}, lastPath);
328 if (!outPortBundle)
329 throw std::runtime_error("dma write test for " + toString(width) +
330 " bits failed. No out port found");
331 WriteChannelPort &writePort = outPortBundle->getRawWrite("data");
333
334 size_t xferCount = 24;
335 uint8_t *data = new uint8_t[width];
336 for (size_t i = 0; i < width / 8; ++i)
337 data[i] = 0;
338 fromHostMMIO->read(8);
339 fromHostMMIO->write(0, xferCount);
340 for (size_t i = 1; i < xferCount + 1; ++i) {
341 data[0] = i;
342 bool successWrite;
343 size_t attempts = 0;
344 do {
345 successWrite = writePort.tryWrite(MessageData(data, width / 8));
346 if (!successWrite) {
347 std::this_thread::sleep_for(std::chrono::milliseconds(10));
348 }
349 } while (!successWrite && ++attempts < 100);
350 if (!successWrite)
351 throw std::runtime_error("dma write test for " + toString(width) +
352 " bits failed. Write failed");
353 uint64_t lastReadMMIO;
354 for (size_t a = 0; a < 20; ++a) {
355 lastReadMMIO = fromHostMMIO->read(8);
356 if (lastReadMMIO == i)
357 break;
358 std::this_thread::sleep_for(std::chrono::milliseconds(10));
359 if (a >= 19)
360 throw std::runtime_error("dma write for " + toString(width) +
361 " bits test failed. Read from MMIO failed");
362 }
363 }
364 writePort.disconnect();
365 delete[] data;
366 logger.info("esitester",
367 "== DMA write test for " + toString(width) + " bits complete");
368}
369
370static void dmaTest(AcceleratorConnection *conn, Accelerator *acc, bool read,
371 bool write) {
372 bool success = true;
373 if (write)
374 for (size_t width : {32, 64, 128, 256, 384, 504, 512})
375 try {
376 dmaWriteTest(conn, acc, width);
377 } catch (std::exception &e) {
378 success = false;
379 std::cerr << "DMA write test for " << width
380 << "bits failed: " << e.what() << std::endl;
381 }
382 if (read)
383 for (size_t width : {32, 64, 128, 256, 384, 504, 512})
384 dmaReadTest(conn, acc, width);
385 if (!success)
386 throw std::runtime_error("DMA test failed");
387}
388
390 size_t width, size_t xferCount) {
391
392 AppIDPath lastPath;
393 BundlePort *toHostMMIOPort = acc->resolvePort(
394 {AppID("tohostdmatest", width), AppID("ToHostDMATest")}, lastPath);
395 if (!toHostMMIOPort)
396 throw std::runtime_error("bandwidth test failed. No tohostdmatest[" +
397 std::to_string(width) + "] found");
398 auto *toHostMMIO = toHostMMIOPort->getAs<services::MMIO::MMIORegion>();
399 if (!toHostMMIO)
400 throw std::runtime_error("bandwidth test failed. MMIO port is not MMIO");
401 lastPath.clear();
402 BundlePort *outPortBundle =
403 acc->resolvePort({AppID("tohostdmatest", width), AppID("out")}, lastPath);
404 ReadChannelPort &outPort = outPortBundle->getRawRead("data");
405 outPort.connect();
406
407 Logger &logger = conn->getLogger();
408 logger.info("esitester", "Starting bandwidth test read with " +
409 std::to_string(xferCount) + " x " +
410 std::to_string(width) + " bit transfers");
411 MessageData data;
412 auto start = std::chrono::high_resolution_clock::now();
413 toHostMMIO->write(0, xferCount);
414 for (size_t i = 0; i < xferCount; ++i) {
415 outPort.read(data);
416 logger.debug(
417 [i, &data](std::string &subsystem, std::string &msg,
418 std::unique_ptr<std::map<std::string, std::any>> &details) {
419 subsystem = "esitester";
420 msg = "Cycle count [" + std::to_string(i) + "] = 0x" + data.toHex();
421 });
422 }
423 auto duration = std::chrono::duration_cast<std::chrono::microseconds>(
424 std::chrono::high_resolution_clock::now() - start);
425 logger.info("esitester",
426 " Bandwidth test: " + std::to_string(xferCount) + " x " +
427 std::to_string(width) + " bit transfers in " +
428 std::to_string(duration.count()) + " microseconds");
429 logger.info("esitester",
430 " bandwidth: " +
431 std::to_string((xferCount * (width / 8) * 1000000) /
432 duration.count() / 1024) +
433 " kbytes/sec");
434}
435
437 size_t width, size_t xferCount) {
438
439 AppIDPath lastPath;
440 BundlePort *fromHostMMIOPort = acc->resolvePort(
441 {AppID("fromhostdmatest", width), AppID("FromHostDMATest")}, lastPath);
442 if (!fromHostMMIOPort)
443 throw std::runtime_error("bandwidth test failed. No tohostdmatest[" +
444 std::to_string(width) + "] found");
445 auto *fromHostMMIO = fromHostMMIOPort->getAs<services::MMIO::MMIORegion>();
446 if (!fromHostMMIO)
447 throw std::runtime_error("bandwidth test failed. MMIO port is not MMIO");
448 lastPath.clear();
449 BundlePort *inPortBundle = acc->resolvePort(
450 {AppID("fromhostdmatest", width), AppID("in")}, lastPath);
451 WriteChannelPort &outPort = inPortBundle->getRawWrite("data");
452 outPort.connect();
453
454 Logger &logger = conn->getLogger();
455 logger.info("esitester", "Starting bandwidth write read with " +
456 std::to_string(xferCount) + " x " +
457 std::to_string(width) + " bit transfers");
458 std::vector<uint8_t> dataVec(width / 8);
459 for (size_t i = 0; i < width / 8; ++i)
460 dataVec[i] = i;
461 MessageData data(dataVec);
462 auto start = std::chrono::high_resolution_clock::now();
463 fromHostMMIO->write(0, xferCount);
464 for (size_t i = 0; i < xferCount; ++i) {
465 outPort.write(data);
466 logger.debug(
467 [i, &data](std::string &subsystem, std::string &msg,
468 std::unique_ptr<std::map<std::string, std::any>> &details) {
469 subsystem = "esitester";
470 msg = "Cycle count [" + std::to_string(i) + "] = 0x" + data.toHex();
471 });
472 }
473 auto duration = std::chrono::duration_cast<std::chrono::microseconds>(
474 std::chrono::high_resolution_clock::now() - start);
475 logger.info("esitester",
476 " Bandwidth test: " + std::to_string(xferCount) + " x " +
477 std::to_string(width) + " bit transfers in " +
478 std::to_string(duration.count()) + " microseconds");
479 logger.info("esitester",
480 " bandwidth: " +
481 std::to_string((xferCount * (width / 8) * 1000000) /
482 duration.count() / 1024) +
483 " kbytes/sec");
484}
485
487 uint32_t xferCount,
488 const std::vector<uint32_t> &widths, bool read,
489 bool write) {
490 if (read)
491 for (size_t width : widths)
492 bandwidthReadTest(conn, acc, width, xferCount);
493 if (write)
494 for (size_t width : widths)
495 bandwidthWriteTest(conn, acc, width, xferCount);
496}
assert(baseType &&"element must be base type")
static void print(TypedAttr val, llvm::raw_ostream &os)
static void writePort(uint16_t port)
Write the port number to a file.
Definition RpcServer.cpp:37
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.
Logger & getLogger() const
Definition Accelerator.h:84
Top level accelerator class.
Definition Accelerator.h:60
Services provide connections to 'bundles' – collections of named, unidirectional communication channe...
Definition Ports.h:226
T * getAs() const
Cast this Bundle port to a subclass which is actually useful.
Definition Ports.h:254
ReadChannelPort & getRawRead(const std::string &name) const
Definition Ports.cpp:35
WriteChannelPort & getRawWrite(const std::string &name) const
Get access to the raw byte streams of a channel.
Definition Ports.cpp:25
Common options and code for ESI runtime tools.
Definition CLI.h:29
Context & getContext()
Get the context.
Definition CLI.h:58
std::unique_ptr< AcceleratorConnection > connect()
Connect to the accelerator using the specified backend and connection.
Definition CLI.h:53
int esiParse(int argc, const char **argv)
Run the parser.
Definition CLI.h:43
AcceleratorConnections, Accelerators, and Manifests must all share a context.
Definition Context.h:31
BundlePort * resolvePort(const AppIDPath &path, AppIDPath &lastLookup) const
Attempt to resolve a path to a port.
Definition Design.cpp:72
const std::map< AppID, BundlePort & > & getPorts() const
Access the module's ports by ID.
Definition Design.h:76
const std::map< AppID, Instance * > & getChildren() const
Access the module's children by ID.
Definition Design.h:67
virtual void info(const std::string &subsystem, const std::string &msg, const std::map< std::string, std::any > *details=nullptr)
Report an informational message.
Definition Logging.h:71
void debug(const std::string &subsystem, const std::string &msg, const std::map< std::string, std::any > *details=nullptr)
Report a debug message.
Definition Logging.h:79
Class to parse a manifest.
Definition Manifest.h:39
A logical chunk of data representing serialized data.
Definition Common.h:103
A ChannelPort which reads data from the accelerator.
Definition Ports.h:124
virtual void connect(std::function< bool(MessageData)> callback, std::optional< unsigned > bufferSize=std::nullopt)
Definition Ports.cpp:44
virtual void disconnect() override
Definition Ports.h:129
virtual void read(MessageData &outData)
Specify a buffer to read into.
Definition Ports.h:165
A ChannelPort which sends data to the accelerator.
Definition Ports.h:77
virtual void write(const MessageData &)=0
A very basic blocking write API.
virtual void connect(std::optional< unsigned > bufferSize=std::nullopt) override
Set up a connection to the accelerator.
Definition Ports.h:82
A function call which gets attached to a service port.
Definition Services.h:304
void connect(std::function< MessageData(const MessageData &)> callback, bool quick=false)
Connect a callback to code which will be executed when the accelerator invokes the callback.
Definition Services.cpp:244
virtual void start()
In cases where necessary, enable host memory services.
Definition Services.h:232
A "slice" of some parent MMIO space.
Definition Services.h:159
Information about the Accelerator system.
Definition Services.h:100
static void bandwidthReadTest(AcceleratorConnection *conn, Accelerator *acc, size_t width, size_t xferCount)
static void dmaWriteTest(AcceleratorConnection *conn, Accelerator *acc, size_t width)
static void bandwidthWriteTest(AcceleratorConnection *conn, Accelerator *acc, size_t width, size_t xferCount)
static void registerCallbacks(AcceleratorConnection *, Accelerator *)
static void bandwidthTest(AcceleratorConnection *, Accelerator *, uint32_t xferCount, const std::vector< uint32_t > &widths, bool read, bool write)
static void dmaReadTest(AcceleratorConnection *conn, Accelerator *acc, size_t width)
static void hostmemTest(AcceleratorConnection *, Accelerator *, bool read, bool write)
int main(int argc, const char *argv[])
Definition esitester.cpp:44
static void dmaTest(AcceleratorConnection *, Accelerator *, bool read, bool write)
Definition esi.py:1
std::string toString(const std::any &a)
'Stringify' a std::any. This is used to log std::any values by some loggers.
Definition Logging.cpp:123
std::string toHex(void *val)
Definition Common.cpp:37
RAII memory region for host memory.
Definition Services.h:208
virtual void * getPtr() const =0
Get a pointer to the host memory.
virtual void flush()
Flush the memory region to ensure that the device sees the latest contents.
Definition Services.h:222