1#include "loopback/LoopbackIP.h"
20 {
AppID(
"loopback_inst", 0),
AppID(
"loopback_tohw")}, lastLookup);
22 throw std::runtime_error(
"No loopback_tohw port found");
24 {
AppID(
"loopback_inst", 0),
AppID(
"loopback_fromhw")}, lastLookup);
26 throw std::runtime_error(
"No loopback_fromhw port found");
34 uint8_t sendVal = 0x5a;
37 uint8_t got = fromHw.
read();
39 throw std::runtime_error(
"Loopback byte mismatch");
41 std::cout <<
"loopback i8 ok: 0x" << std::hex << (int)got << std::dec <<
"\n";
48 throw std::runtime_error(
"No structFunc port found");
55 esi_system::ArgStruct arg{};
57 arg.b =
static_cast<int8_t
>(-7);
59 esi_system::ResultStruct res = func.
call(arg).get();
61 int8_t expectedX =
static_cast<int8_t
>(arg.b + 1);
62 if (res.x != expectedX || res.y != arg.b)
63 throw std::runtime_error(
"Struct func result mismatch");
65 std::cout <<
"struct func ok: b=" << (int)arg.b <<
" x=" << (
int)res.x
66 <<
" y=" << (int)res.y <<
"\n";
73 throw std::runtime_error(
"No oddStructFunc port found");
80 esi_system::OddStruct arg{};
82 arg.b =
static_cast<int8_t
>(-17);
84 arg.inner.q =
static_cast<int8_t
>(-7);
88 esi_system::OddStruct res = func.
call(arg).get();
90 uint16_t expectA =
static_cast<uint16_t
>(arg.a + 1);
91 int8_t expectB =
static_cast<int8_t
>(arg.b - 3);
92 uint8_t expectP =
static_cast<uint8_t
>(arg.inner.p + 5);
93 int8_t expectQ =
static_cast<int8_t
>(arg.inner.q + 2);
94 uint8_t expectR0 =
static_cast<uint8_t
>(arg.inner.r[0] + 1);
95 uint8_t expectR1 =
static_cast<uint8_t
>(arg.inner.r[1] + 2);
96 if (res.a != expectA || res.b != expectB || res.inner.p != expectP ||
97 res.inner.q != expectQ || res.inner.r[0] != expectR0 ||
98 res.inner.r[1] != expectR1)
99 throw std::runtime_error(
"Odd struct func result mismatch");
101 std::cout <<
"odd struct func ok: a=" << res.a <<
" b=" << (int)res.b
102 <<
" p=" << (
int)res.inner.p <<
" q=" << (int)res.inner.q
103 <<
" r0=" << (
int)res.inner.r[0] <<
" r1=" << (int)res.inner.r[1]
111 throw std::runtime_error(
"No arrayFunc port found");
115 throw std::runtime_error(
"arrayFunc not a FuncService::Function");
118 int8_t argArray[1] = {
static_cast<int8_t
>(-3)};
120 func->call(
MessageData(
reinterpret_cast<const uint8_t *
>(argArray),
124 const auto *res = resMsg.
as<esi_system::ResultArray>();
125 int8_t a = (*res)[0];
126 int8_t b = (*res)[1];
127 int8_t expect0 = argArray[0];
128 int8_t expect1 =
static_cast<int8_t
>(argArray[0] + 1);
130 bool ok = (a == expect0 && b == expect1) || (a == expect1 && b == expect0);
132 throw std::runtime_error(
"Array func result mismatch");
141 std::cout <<
"array func ok: " << (int)low <<
" " << (
int)high <<
"\n";
148 throw std::runtime_error(
"No sint4Func port found");
158 int8_t posResult = func.
call(posArg).get();
159 if (posResult != posArg)
160 throw std::runtime_error(
"sint4 loopback positive mismatch: got " +
161 std::to_string(posResult));
165 int8_t negResult = func.
call(negArg).get();
166 if (negResult != negArg)
167 throw std::runtime_error(
"sint4 loopback negative mismatch: got " +
168 std::to_string(negResult));
170 std::cout <<
"sint4 loopback ok: pos=" << (int)posResult
171 <<
" neg=" << (
int)negResult <<
"\n";
198 size_t numCoords = 100;
199 uint32_t xTrans = 10, yTrans = 20;
202 std::mt19937 rng(0xDEADBEEF);
203 std::uniform_int_distribution<uint32_t> dist(0, 1000000);
204 std::vector<SerialCoordValue> coords;
205 coords.reserve(numCoords);
206 for (uint32_t i = 0; i < numCoords; ++i)
207 coords.emplace_back(dist(rng), dist(rng));
211 throw std::runtime_error(
"Serial coord translate test: no "
212 "'coord_translator_serial' child found");
214 auto &ports = child->second->getPorts();
215 auto portIter = ports.find(
AppID(
"translate_coords_serial"));
216 if (portIter == ports.end())
217 throw std::runtime_error(
218 "Serial coord translate test: no 'translate_coords_serial' port found");
222 throw std::runtime_error(
223 "Serial coord translate test: port is not a FuncService::Function");
229 func->getRawWrite(
"arg"));
235 auto batch = std::make_unique<SerialCoordInput>(xTrans, yTrans, coords);
236 argPort.
write(batch);
238 std::vector<SerialCoordValue> results;
241 resultPort.
read(msg);
243 throw std::runtime_error(
"Unexpected result message size");
251 for (uint16_t i = 0; i < batchCount; ++i) {
252 resultPort.
read(msg);
254 throw std::runtime_error(
"Unexpected result message size");
257 results.push_back({dFrame->data.y, dFrame->data.x});
261 if (results.size() != coords.size())
262 throw std::runtime_error(
"Serial coord translate result size mismatch");
263 for (
size_t i = 0; i < coords.size(); ++i) {
264 uint32_t expX = coords[i].x + xTrans;
265 uint32_t expY = coords[i].y + yTrans;
266 if (results[i].x != expX || results[i].y != expY)
267 throw std::runtime_error(
"Serial coord translate result mismatch");
274int main(
int argc,
const char *argv[]) {
277 "Loopback cosim test using generated ESI headers and typed ports.");
278 if (
int rc = cli.
esiParse(argc, argv))
280 if (!cli.get_help_ptr()->empty())
287 Manifest manifest(ctxt, info.getJsonManifest());
288 Accelerator *accel = manifest.buildAccelerator(*conn);
289 conn->getServiceThread()->addPoll(*accel);
291 std::cout <<
"depth: 0x" << std::hex << esi_system::LoopbackIP::depth
302 }
catch (std::exception &e) {
Abstract class representing a connection to an accelerator.
Top level accelerator class.
Services provide connections to 'bundles' – collections of named, unidirectional communication channe...
T * getAs() const
Cast this Bundle port to a subclass which is actually useful.
ReadChannelPort & getRawRead(const std::string &name) const
WriteChannelPort & getRawWrite(const std::string &name) const
Get access to the raw byte streams of a channel.
Common options and code for ESI runtime tools.
Context & getContext()
Get the context.
AcceleratorConnection * connect()
Connect to the accelerator using the specified backend and connection.
int esiParse(int argc, const char **argv)
Run the parser.
AcceleratorConnections, Accelerators, and Manifests must all share a context.
BundlePort * resolvePort(const AppIDPath &path, AppIDPath &lastLookup) const
Attempt to resolve a path to a port.
const std::map< AppID, Instance * > & getChildren() const
Access the module's children by ID.
virtual void error(const std::string &subsystem, const std::string &msg, const std::map< std::string, std::any > *details=nullptr)
Report an error.
Class to parse a manifest.
A logical chunk of data representing serialized data.
const uint8_t * getBytes() const
const T * as() const
Cast to a type.
size_t getSize() const
Get the size of the data in bytes.
A ChannelPort which reads data from the accelerator.
virtual void connect(std::function< bool(MessageData)> callback, const ConnectOptions &options={})
virtual void disconnect() override
virtual void read(MessageData &outData)
Specify a buffer to read into.
std::future< ResultT > call(const ArgT &arg)
void connect(const ChannelPort::ConnectOptions &opts={})
void connect(const ChannelPort::ConnectOptions &opts={})
void write(const T &data)
A function call which gets attached to a service port.
Information about the Accelerator system.
esi_system::serial_coord_args SerialCoordInput
static void runOddStructFunc(Accelerator *accel)
int main(int argc, const char *argv[])
static void serialCoordTranslateTest(Accelerator *accel)
static void runLoopbackI8(Accelerator *accel)
SerialCoordInput::value_type SerialCoordValue
static void runStructFunc(Accelerator *accel)
static void runArrayFunc(Accelerator *accel)
static void runSInt4Loopback(Accelerator *accel)
SerialCoordOutputData data
SerialCoordOutputHeader header