CIRCT 23.0.0git
Loading...
Searching...
No Matches
loopback.cpp
Go to the documentation of this file.
1#include "loopback/LoopbackIP.h"
2
3#include "esi/Accelerator.h"
4#include "esi/CLI.h"
5#include "esi/Manifest.h"
6#include "esi/Services.h"
7
8#include <cstdint>
9#include <iostream>
10#include <stdexcept>
11
12using namespace esi;
13
14static void runLoopbackI8(Accelerator *accel) {
15 AppIDPath lastLookup;
16 BundlePort *inPort = accel->resolvePort(
17 {AppID("loopback_inst", 0), AppID("loopback_tohw")}, lastLookup);
18 if (!inPort)
19 throw std::runtime_error("No loopback_tohw port found");
20 BundlePort *outPort = accel->resolvePort(
21 {AppID("loopback_inst", 0), AppID("loopback_fromhw")}, lastLookup);
22 if (!outPort)
23 throw std::runtime_error("No loopback_fromhw port found");
24
25 WriteChannelPort &toHw = inPort->getRawWrite("recv");
26 ReadChannelPort &fromHw = outPort->getRawRead("send");
27 toHw.connect();
28 fromHw.connect();
29
30 uint8_t sendVal = 0x5a;
31 toHw.write(MessageData(&sendVal, sizeof(sendVal)));
32
33 MessageData recvMsg;
34 fromHw.read(recvMsg);
35 if (recvMsg.getSize() != sizeof(uint8_t))
36 throw std::runtime_error("Unexpected loopback recv size");
37 uint8_t got = *recvMsg.as<uint8_t>();
38 if (got != sendVal)
39 throw std::runtime_error("Loopback byte mismatch");
40
41 std::cout << "loopback i8 ok: 0x" << std::hex << (int)got << std::dec << "\n";
42}
43
44static void runStructFunc(Accelerator *accel) {
45 AppIDPath lastLookup;
46 BundlePort *port = accel->resolvePort({AppID("structFunc")}, lastLookup);
47 if (!port)
48 throw std::runtime_error("No structFunc port found");
49
50 auto *func = port->getAs<services::FuncService::Function>();
51 if (!func)
52 throw std::runtime_error("structFunc not a FuncService::Function");
53 func->connect();
54
55 esi_system::ArgStruct arg{};
56 arg.a = 0x1234;
57 arg.b = static_cast<int8_t>(-7);
58
59 MessageData resMsg = func->call(MessageData::from(arg)).get();
60 const auto *res = resMsg.as<esi_system::ResultStruct>();
61
62 int8_t expectedX = static_cast<int8_t>(arg.b + 1);
63 if (res->x != expectedX || res->y != arg.b)
64 throw std::runtime_error("Struct func result mismatch");
65
66 std::cout << "struct func ok: b=" << (int)arg.b << " x=" << (int)res->x
67 << " y=" << (int)res->y << "\n";
68}
69
70static void runOddStructFunc(Accelerator *accel) {
71 AppIDPath lastLookup;
72 BundlePort *port = accel->resolvePort({AppID("oddStructFunc")}, lastLookup);
73 if (!port)
74 throw std::runtime_error("No oddStructFunc port found");
75
76 auto *func = port->getAs<services::FuncService::Function>();
77 if (!func)
78 throw std::runtime_error("oddStructFunc not a FuncService::Function");
79 func->connect();
80
81 esi_system::OddStruct arg{};
82 arg.a = 0xabc;
83 arg.b = static_cast<int8_t>(-17);
84 arg.inner.p = 5;
85 arg.inner.q = static_cast<int8_t>(-7);
86 arg.inner.r[0] = 3;
87 arg.inner.r[1] = 4;
88
89 MessageData resMsg = func->call(MessageData::from(arg)).get();
90 const auto *res = resMsg.as<esi_system::OddStruct>();
91
92 uint16_t expectA = static_cast<uint16_t>(arg.a + 1);
93 int8_t expectB = static_cast<int8_t>(arg.b - 3);
94 uint8_t expectP = static_cast<uint8_t>(arg.inner.p + 5);
95 int8_t expectQ = static_cast<int8_t>(arg.inner.q + 2);
96 uint8_t expectR0 = static_cast<uint8_t>(arg.inner.r[0] + 1);
97 uint8_t expectR1 = static_cast<uint8_t>(arg.inner.r[1] + 2);
98 if (res->a != expectA || res->b != expectB || res->inner.p != expectP ||
99 res->inner.q != expectQ || res->inner.r[0] != expectR0 ||
100 res->inner.r[1] != expectR1)
101 throw std::runtime_error("Odd struct func result mismatch");
102
103 std::cout << "odd struct func ok: a=" << res->a << " b=" << (int)res->b
104 << " p=" << (int)res->inner.p << " q=" << (int)res->inner.q
105 << " r0=" << (int)res->inner.r[0] << " r1=" << (int)res->inner.r[1]
106 << "\n";
107}
108
109static void runArrayFunc(Accelerator *accel) {
110 AppIDPath lastLookup;
111 BundlePort *port = accel->resolvePort({AppID("arrayFunc")}, lastLookup);
112 if (!port)
113 throw std::runtime_error("No arrayFunc port found");
114
115 auto *func = port->getAs<services::FuncService::Function>();
116 if (!func)
117 throw std::runtime_error("arrayFunc not a FuncService::Function");
118 func->connect();
119
120 int8_t argArray[1] = {static_cast<int8_t>(-3)};
121 MessageData resMsg =
122 func->call(MessageData(reinterpret_cast<const uint8_t *>(argArray),
123 sizeof(argArray)))
124 .get();
125
126 const auto *res = resMsg.as<esi_system::ResultArray>();
127 int8_t a = (*res)[0];
128 int8_t b = (*res)[1];
129 int8_t expect0 = argArray[0];
130 int8_t expect1 = static_cast<int8_t>(argArray[0] + 1);
131
132 bool ok = (a == expect0 && b == expect1) || (a == expect1 && b == expect0);
133 if (!ok)
134 throw std::runtime_error("Array func result mismatch");
135
136 int8_t low = a;
137 int8_t high = b;
138 if (low > high) {
139 int8_t tmp = low;
140 low = high;
141 high = tmp;
142 }
143 std::cout << "array func ok: " << (int)low << " " << (int)high << "\n";
144}
145
146int main(int argc, const char *argv[]) {
147 CliParser cli("loopback-cpp");
148 cli.description("Loopback cosim test using generated ESI headers.");
149 if (int rc = cli.esiParse(argc, argv))
150 return rc;
151 if (!cli.get_help_ptr()->empty())
152 return 0;
153
154 Context &ctxt = cli.getContext();
155 AcceleratorConnection *conn = cli.connect();
156 try {
157 const auto &info = *conn->getService<services::SysInfo>();
158 Manifest manifest(ctxt, info.getJsonManifest());
159 Accelerator *accel = manifest.buildAccelerator(*conn);
160 conn->getServiceThread()->addPoll(*accel);
161
162 std::cout << "depth: 0x" << std::hex << esi_system::LoopbackIP::depth
163 << std::dec << "\n";
164
165 runLoopbackI8(accel);
166 runStructFunc(accel);
167 runOddStructFunc(accel);
168 runArrayFunc(accel);
169
170 conn->disconnect();
171 } catch (std::exception &e) {
172 ctxt.getLogger().error("loopback-cpp", e.what());
173 conn->disconnect();
174 return 1;
175 }
176
177 return 0;
178}
Abstract class representing a connection to an accelerator.
Definition Accelerator.h:89
Top level accelerator class.
Definition Accelerator.h:70
Services provide connections to 'bundles' – collections of named, unidirectional communication channe...
Definition Ports.h:433
T * getAs() const
Cast this Bundle port to a subclass which is actually useful.
Definition Ports.h:461
ReadChannelPort & getRawRead(const std::string &name) const
Definition Ports.cpp:52
WriteChannelPort & getRawWrite(const std::string &name) const
Get access to the raw byte streams of a channel.
Definition Ports.cpp:42
Common options and code for ESI runtime tools.
Definition CLI.h:29
Context & getContext()
Get the context.
Definition CLI.h:63
AcceleratorConnection * connect()
Connect to the accelerator using the specified backend and connection.
Definition CLI.h:60
int esiParse(int argc, const char **argv)
Run the parser.
Definition CLI.h:46
AcceleratorConnections, Accelerators, and Manifests must all share a context.
Definition Context.h:34
Logger & getLogger()
Definition Context.h:69
BundlePort * resolvePort(const AppIDPath &path, AppIDPath &lastLookup) const
Attempt to resolve a path to a port.
Definition Design.cpp:72
virtual void error(const std::string &subsystem, const std::string &msg, const std::map< std::string, std::any > *details=nullptr)
Report an error.
Definition Logging.h:64
Class to parse a manifest.
Definition Manifest.h:39
A logical chunk of data representing serialized data.
Definition Common.h:113
const T * as() const
Cast to a type.
Definition Common.h:148
size_t getSize() const
Get the size of the data in bytes.
Definition Common.h:138
static MessageData from(T &t)
Cast from a type to its raw bytes.
Definition Common.h:158
A ChannelPort which reads data from the accelerator.
Definition Ports.h:318
virtual void connect(std::function< bool(MessageData)> callback, const ConnectOptions &options={})
Definition Ports.cpp:69
virtual void read(MessageData &outData)
Specify a buffer to read into.
Definition Ports.h:358
A ChannelPort which sends data to the accelerator.
Definition Ports.h:206
void write(const MessageData &data)
A very basic blocking write API.
Definition Ports.h:222
virtual void connect(const ConnectOptions &options={}) override
Set up a connection to the accelerator.
Definition Ports.h:210
A function call which gets attached to a service port.
Definition Services.h:291
Information about the Accelerator system.
Definition Services.h:113
static void runOddStructFunc(Accelerator *accel)
Definition loopback.cpp:70
int main(int argc, const char *argv[])
Definition loopback.cpp:146
static void runLoopbackI8(Accelerator *accel)
Definition loopback.cpp:14
static void runStructFunc(Accelerator *accel)
Definition loopback.cpp:44
static void runArrayFunc(Accelerator *accel)
Definition loopback.cpp:109
Definition esi.py:1