CIRCT 23.0.0git
Loading...
Searching...
No Matches
loopback_typed.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#include "esi/TypedPorts.h"
8
9#include <cstdint>
10#include <iostream>
11#include <stdexcept>
12
13using namespace esi;
14
15static void runLoopbackI8(Accelerator *accel) {
16 AppIDPath lastLookup;
17 BundlePort *inPort = accel->resolvePort(
18 {AppID("loopback_inst", 0), AppID("loopback_tohw")}, lastLookup);
19 if (!inPort)
20 throw std::runtime_error("No loopback_tohw port found");
21 BundlePort *outPort = accel->resolvePort(
22 {AppID("loopback_inst", 0), AppID("loopback_fromhw")}, lastLookup);
23 if (!outPort)
24 throw std::runtime_error("No loopback_fromhw port found");
25
26 // Use TypedWritePort and TypedReadPort instead of raw channels.
27 TypedWritePort<uint8_t> toHw(inPort->getRawWrite("recv"));
28 TypedReadPort<uint8_t> fromHw(outPort->getRawRead("send"));
29 toHw.connect();
30 fromHw.connect();
31
32 uint8_t sendVal = 0x5a;
33 toHw.write(sendVal);
34
35 uint8_t got = fromHw.read();
36 if (got != sendVal)
37 throw std::runtime_error("Loopback byte mismatch");
38
39 std::cout << "loopback i8 ok: 0x" << std::hex << (int)got << std::dec << "\n";
40}
41
42static void runStructFunc(Accelerator *accel) {
43 AppIDPath lastLookup;
44 BundlePort *port = accel->resolvePort({AppID("structFunc")}, lastLookup);
45 if (!port)
46 throw std::runtime_error("No structFunc port found");
47
48 // Use TypedFunction instead of raw FuncService::Function.
51 func.connect();
52
53 esi_system::ArgStruct arg{};
54 arg.a = 0x1234;
55 arg.b = static_cast<int8_t>(-7);
56
57 esi_system::ResultStruct res = func.call(arg).get();
58
59 int8_t expectedX = static_cast<int8_t>(arg.b + 1);
60 if (res.x != expectedX || res.y != arg.b)
61 throw std::runtime_error("Struct func result mismatch");
62
63 std::cout << "struct func ok: b=" << (int)arg.b << " x=" << (int)res.x
64 << " y=" << (int)res.y << "\n";
65}
66
67static void runOddStructFunc(Accelerator *accel) {
68 AppIDPath lastLookup;
69 BundlePort *port = accel->resolvePort({AppID("oddStructFunc")}, lastLookup);
70 if (!port)
71 throw std::runtime_error("No oddStructFunc port found");
72
73 // Use TypedFunction with OddStruct for both arg and result.
76 func.connect();
77
78 esi_system::OddStruct arg{};
79 arg.a = 0xabc;
80 arg.b = static_cast<int8_t>(-17);
81 arg.inner.p = 5;
82 arg.inner.q = static_cast<int8_t>(-7);
83 arg.inner.r[0] = 3;
84 arg.inner.r[1] = 4;
85
86 esi_system::OddStruct res = func.call(arg).get();
87
88 uint16_t expectA = static_cast<uint16_t>(arg.a + 1);
89 int8_t expectB = static_cast<int8_t>(arg.b - 3);
90 uint8_t expectP = static_cast<uint8_t>(arg.inner.p + 5);
91 int8_t expectQ = static_cast<int8_t>(arg.inner.q + 2);
92 uint8_t expectR0 = static_cast<uint8_t>(arg.inner.r[0] + 1);
93 uint8_t expectR1 = static_cast<uint8_t>(arg.inner.r[1] + 2);
94 if (res.a != expectA || res.b != expectB || res.inner.p != expectP ||
95 res.inner.q != expectQ || res.inner.r[0] != expectR0 ||
96 res.inner.r[1] != expectR1)
97 throw std::runtime_error("Odd struct func result mismatch");
98
99 std::cout << "odd struct func ok: a=" << res.a << " b=" << (int)res.b
100 << " p=" << (int)res.inner.p << " q=" << (int)res.inner.q
101 << " r0=" << (int)res.inner.r[0] << " r1=" << (int)res.inner.r[1]
102 << "\n";
103}
104
105static void runArrayFunc(Accelerator *accel) {
106 AppIDPath lastLookup;
107 BundlePort *port = accel->resolvePort({AppID("arrayFunc")}, lastLookup);
108 if (!port)
109 throw std::runtime_error("No arrayFunc port found");
110
111 auto *func = port->getAs<services::FuncService::Function>();
112 if (!func)
113 throw std::runtime_error("arrayFunc not a FuncService::Function");
114 func->connect();
115
116 int8_t argArray[1] = {static_cast<int8_t>(-3)};
117 MessageData resMsg =
118 func->call(MessageData(reinterpret_cast<const uint8_t *>(argArray),
119 sizeof(argArray)))
120 .get();
121
122 const auto *res = resMsg.as<esi_system::ResultArray>();
123 int8_t a = (*res)[0];
124 int8_t b = (*res)[1];
125 int8_t expect0 = argArray[0];
126 int8_t expect1 = static_cast<int8_t>(argArray[0] + 1);
127
128 bool ok = (a == expect0 && b == expect1) || (a == expect1 && b == expect0);
129 if (!ok)
130 throw std::runtime_error("Array func result mismatch");
131
132 int8_t low = a;
133 int8_t high = b;
134 if (low > high) {
135 int8_t tmp = low;
136 low = high;
137 high = tmp;
138 }
139 std::cout << "array func ok: " << (int)low << " " << (int)high << "\n";
140}
141
142static void runSInt4Loopback(Accelerator *accel) {
143 AppIDPath lastLookup;
144 BundlePort *port = accel->resolvePort({AppID("sint4Func")}, lastLookup);
145 if (!port)
146 throw std::runtime_error("No sint4Func port found");
147
148 // Use TypedFunction<int8_t, int8_t> for si4 → si4 loopback.
149 // si4 fits in int8_t (width 4 <= 8). Tests sign extension of small widths.
152 func.connect();
153
154 // Test positive value.
155 int8_t posArg = 5;
156 int8_t posResult = func.call(posArg).get();
157 if (posResult != posArg)
158 throw std::runtime_error("sint4 loopback positive mismatch: got " +
159 std::to_string(posResult));
160
161 // Test negative value (-3, which is 0x0D in si4 wire format).
162 int8_t negArg = -3;
163 int8_t negResult = func.call(negArg).get();
164 if (negResult != negArg)
165 throw std::runtime_error("sint4 loopback negative mismatch: got " +
166 std::to_string(negResult));
167
168 std::cout << "sint4 loopback ok: pos=" << (int)posResult
169 << " neg=" << (int)negResult << "\n";
170}
171
172int main(int argc, const char *argv[]) {
173 CliParser cli("loopback-typed-cpp");
174 cli.description(
175 "Loopback cosim test using generated ESI headers and typed ports.");
176 if (int rc = cli.esiParse(argc, argv))
177 return rc;
178 if (!cli.get_help_ptr()->empty())
179 return 0;
180
181 Context &ctxt = cli.getContext();
182 AcceleratorConnection *conn = cli.connect();
183 try {
184 const auto &info = *conn->getService<services::SysInfo>();
185 Manifest manifest(ctxt, info.getJsonManifest());
186 Accelerator *accel = manifest.buildAccelerator(*conn);
187 conn->getServiceThread()->addPoll(*accel);
188
189 std::cout << "depth: 0x" << std::hex << esi_system::LoopbackIP::depth
190 << std::dec << "\n";
191
192 runLoopbackI8(accel);
193 runSInt4Loopback(accel);
194 runStructFunc(accel);
195 runOddStructFunc(accel);
196 runArrayFunc(accel);
197
198 conn->disconnect();
199 } catch (std::exception &e) {
200 ctxt.getLogger().error("loopback-typed-cpp", e.what());
201 conn->disconnect();
202 return 1;
203 }
204
205 return 0;
206}
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
std::future< ResultT > call(const ArgT &arg)
Definition TypedPorts.h:456
void connect(const ChannelPort::ConnectOptions &opts={})
Definition TypedPorts.h:335
void connect(const ChannelPort::ConnectOptions &opts={})
Definition TypedPorts.h:230
void write(const T &data)
Definition TypedPorts.h:238
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)
int main(int argc, const char *argv[])
static void runLoopbackI8(Accelerator *accel)
static void runStructFunc(Accelerator *accel)
static void runArrayFunc(Accelerator *accel)
static void runSInt4Loopback(Accelerator *accel)
Definition esi.py:1