36int main(
int argc,
const char *argv[]) {
39 std::cerr <<
"Expected usage: " << argv[0]
40 <<
" <backend> <connection specifier> [command]" << std::endl;
44 const char *backend = argv[1];
45 const char *conn = argv[2];
51 Context ctxt = Context::withLogger<StreamLogger>(Logger::Level::Debug);
52 std::unique_ptr<AcceleratorConnection> acc = ctxt.connect(backend, conn);
54 Manifest manifest(ctxt, info.getJsonManifest());
55 Accelerator *accel = manifest.buildAccelerator(*acc);
56 acc->getServiceThread()->addPoll(*accel);
61 std::this_thread::sleep_for(std::chrono::milliseconds(100));
63 }
else if (cmd ==
"wait") {
65 std::this_thread::sleep_for(std::chrono::seconds(1));
66 }
else if (cmd ==
"dmatest") {
67 dmaTest(acc.get(), accel,
true,
true);
68 }
else if (cmd ==
"dmareadtest") {
69 dmaTest(acc.get(), accel,
true,
false);
70 }
else if (cmd ==
"dmawritetest") {
71 dmaTest(acc.get(), accel,
false,
true);
75 std::cout <<
"Exiting successfully\n";
78 }
catch (std::exception &e) {
79 std::cout <<
"Error: " << e.what() << std::endl;
86 auto f = ports.find(
AppID(
"PrintfExample"));
87 if (f != ports.end()) {
93 [&](std::string &subsystem, std::string &msg,
94 std::unique_ptr<std::map<std::string, std::any>> &details) {
95 subsystem =
"ESITESTER";
96 msg =
"Received PrintfExample message";
97 details = std::make_unique<std::map<std::string, std::any>>();
98 details->emplace(
"data", data);
100 std::cout <<
"PrintfExample: " << *data.as<uint32_t>() << std::endl;
105 std::cerr <<
"PrintfExample port is not a CallService::Callback"
108 std::cerr <<
"No PrintfExample port found" << std::endl;
114 uint32_t width,
void *devicePtr,
bool read,
bool write) {
115 std::cout <<
"Running DMA test with width " << width << std::endl;
116 uint64_t *dataPtr =
static_cast<uint64_t *
>(region.
getPtr());
121 throw std::runtime_error(
"DMA test failed. No readmem child found");
122 auto &readMemPorts = readMemChildIter->second->getPorts();
123 auto readMemPortIter = readMemPorts.find(
AppID(
"ReadMem"));
124 if (readMemPortIter == readMemPorts.end())
125 throw std::runtime_error(
"DMA test failed. No ReadMem port found");
128 throw std::runtime_error(
"DMA test failed. ReadMem port is not MMIO");
130 for (
size_t i = 0; i < 8; ++i) {
131 dataPtr[0] = 0x12345678 << i;
132 dataPtr[1] = 0xDEADBEEF << i;
134 readMem->write(8,
reinterpret_cast<uint64_t
>(devicePtr));
139 uint64_t expected = dataPtr[0];
141 expected &= ((1ull << width) - 1);
142 for (
int i = 0; i < 100; ++i) {
143 val = readMem->read(0);
146 std::this_thread::sleep_for(std::chrono::microseconds(100));
150 throw std::runtime_error(
"DMA read test failed. Expected " +
159 auto check = [&](
bool print) {
161 for (
size_t i = 0; i < 8; ++i) {
163 std::cout <<
"dataPtr[" << i <<
"] = 0x" <<
esi::toHex(dataPtr[i])
165 if (i < (width + 63) / 64 && dataPtr[i] == 0xFFFFFFFFFFFFFFFFull)
173 throw std::runtime_error(
"DMA test failed. No writemem child found");
174 auto &writeMemPorts = writeMemChildIter->second->getPorts();
175 auto writeMemPortIter = writeMemPorts.find(
AppID(
"WriteMem"));
176 if (writeMemPortIter == writeMemPorts.end())
177 throw std::runtime_error(
"DMA test failed. No WriteMem port found");
181 throw std::runtime_error(
"DMA test failed. WriteMem port is not MMIO");
183 for (
size_t i = 0, e = 8; i < e; ++i)
184 dataPtr[i] = 0xFFFFFFFFFFFFFFFFull;
189 writeMem->write(0,
reinterpret_cast<uint64_t
>(devicePtr));
191 for (
int i = 0; i < 100; ++i) {
194 std::this_thread::sleep_for(std::chrono::microseconds(100));
197 throw std::runtime_error(
"DMA write test failed");
200 size_t widthInBytes = width / 8;
201 uint8_t *dataPtr8 =
reinterpret_cast<uint8_t *
>(region.
getPtr());
202 for (
size_t i = widthInBytes; i < 64; ++i) {
203 std::cout <<
"endcheck dataPtr8[" << i <<
"] = 0x"
205 if (dataPtr8[i] != 0xFF)
206 throw std::runtime_error(
"DMA write test failed -- write went too far");
216 auto scratchRegion = hostmem->allocate(64, {});
217 uint64_t *dataPtr =
static_cast<uint64_t *
>(scratchRegion->getPtr());
218 for (
size_t i = 0; i < 8; ++i)
220 scratchRegion->flush();
222 dmaTest(acc, *scratchRegion, 32, scratchRegion->getDevicePtr(), read, write);
223 dmaTest(acc, *scratchRegion, 64, scratchRegion->getDevicePtr(), read, write);
224 dmaTest(acc, *scratchRegion, 96, scratchRegion->getDevicePtr(), read, write);
assert(baseType &&"element must be base type")
static void print(TypedAttr val, llvm::raw_ostream &os)
Abstract class representing a connection to an accelerator.
ServiceClass * getService(AppIDPath id={}, std::string implName={}, ServiceImplDetails details={}, HWClientDetails clients={})
Get a typed reference to a particular service type.
Logger & getLogger() const
Top level accelerator class.
AcceleratorConnections, Accelerators, and Manifests must all share a context.
const std::map< AppID, const BundlePort & > & getPorts() const
Access the module's ports by ID.
const std::map< AppID, Instance * > & getChildren() const
Access the module's children by ID.
void debug(const std::string &subsystem, const std::string &msg, const std::map< std::string, std::any > *details=nullptr)
Report a debug message.
Class to parse a manifest.
A logical chunk of data representing serialized data.
A function call which gets attached to a service port.
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.
virtual void start()
In cases where necessary, enable host memory services.
A "slice" of some parent MMIO space.
Information about the Accelerator system.
static void dmaTest(AcceleratorConnection *, Accelerator *, bool read, bool write)
static void registerCallbacks(AcceleratorConnection *, Accelerator *)
int main(int argc, const char *argv[])
std::string toHex(void *val)
RAII memory region for host memory.
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.