11#include "test_codegen/CallServiceCallback.h"
12#include "test_codegen/CallbackWindowedList.h"
13#include "test_codegen/ChannelWindowedListRead.h"
14#include "test_codegen/ChannelWindowedListWrite.h"
15#include "test_codegen/CustomServiceDeclChannel.h"
16#include "test_codegen/IndexedFuncGroup.h"
17#include "test_codegen/MmioReadWrite.h"
18#include "test_codegen/TelemetryMetric.h"
19#include "test_codegen/TypedFuncArrayResult.h"
20#include "test_codegen/TypedFuncMultiArg.h"
21#include "test_codegen/TypedFuncNestedStruct.h"
22#include "test_codegen/TypedFuncStruct.h"
23#include "test_codegen/TypedFuncSubByteSigned.h"
24#include "test_codegen/TypedFuncVoidArg.h"
25#include "test_codegen/TypedFuncVoidResult.h"
26#include "test_codegen/TypedFuncWindowedList.h"
27#include "test_codegen/TypedReadChannelStruct.h"
28#include "test_codegen/TypedWriteChannelByte.h"
54 throw std::runtime_error(std::string(
"test_codegen instance '") +
55 appidName +
"' not found");
63 esi_system::TypedFuncMultiArg mod(
64 findInst(accel,
"typed_func_multi_arg_inst"));
65 auto c = mod.connect();
69 uint32_t got = c->call(7u, 6u).get();
71 throw std::runtime_error(
"typed_func_multi_arg: expected 42, got " +
73 std::cout <<
"typed_func_multi_arg ok\n";
81 esi_system::TypedFuncVoidArg mod(
findInst(accel,
"typed_func_void_arg_inst"));
82 auto c = mod.connect();
84 uint32_t got = c->call().get();
85 if (got != 0xCAFEF00Du)
86 throw std::runtime_error(
87 "typed_func_void_arg: expected 0xCAFEF00D, got 0x" +
toHex(got));
88 std::cout <<
"typed_func_void_arg ok\n";
96 esi_system::TypedFuncVoidResult mod(
97 findInst(accel,
"typed_func_void_result_inst"));
98 auto c = mod.connect();
103 c->call(esi_system::AckArgs(0x5A, 0x1234)).get();
104 std::cout <<
"typed_func_void_result ok\n";
112 esi_system::CallServiceCallback mod(
113 findInst(accel,
"call_service_callback_inst"));
114 auto c = mod.connect();
120 std::atomic<bool> got_call(
false);
121 esi_system::NotifyArgs seen{};
122 c->callback.connect([&](
const esi_system::NotifyArgs &a) {
124 got_call.store(
true, std::memory_order_release);
130 constexpr uint32_t kPayload = 0xDEADBEEFu;
131 c->trigger.write(0x10,
static_cast<uint64_t
>(kPayload));
134 using clock = std::chrono::steady_clock;
135 auto deadline = clock::now() + std::chrono::seconds(5);
136 while (!got_call.load(std::memory_order_acquire) && clock::now() < deadline)
137 std::this_thread::sleep_for(std::chrono::milliseconds(10));
138 if (!got_call.load(std::memory_order_acquire))
139 throw std::runtime_error(
140 "call_service_callback: callback did not fire within timeout");
142 if (seen.tag != 0xA5)
143 throw std::runtime_error(
144 "call_service_callback: wrong tag, expected 0xA5 got 0x" +
145 toHex(
static_cast<uint64_t
>(seen.tag)));
146 if (seen.payload != kPayload)
147 throw std::runtime_error(
148 "call_service_callback: wrong payload, expected 0x" +
toHex(kPayload) +
149 " got 0x" +
toHex(seen.payload));
150 std::cout <<
"call_service_callback ok\n";
158 esi_system::TypedReadChannelStruct mod(
159 findInst(accel,
"typed_read_channel_struct_inst"));
160 auto c = mod.connect();
163 constexpr size_t kNum = esi_system::TypedReadChannelStruct::num_events;
164 for (
size_t i = 1; i <= kNum; ++i) {
165 auto ev = c->data.read();
167 throw std::runtime_error(
168 "typed_read_channel_struct: null read result at i=" +
171 throw std::runtime_error(
172 "typed_read_channel_struct: wrong ts at i=" + std::to_string(i) +
173 ", got " + std::to_string(ev->ts));
174 int32_t expected = -
static_cast<int32_t
>(i);
175 if (ev->val != expected)
176 throw std::runtime_error(
177 "typed_read_channel_struct: wrong val at i=" + std::to_string(i) +
178 ", got " + std::to_string(ev->val));
180 std::cout <<
"typed_read_channel_struct ok (" << kNum <<
" events)\n";
188 esi_system::TypedWriteChannelByte mod(
189 findInst(accel,
"typed_write_channel_byte_inst"));
190 auto c = mod.connect();
195 static constexpr uint8_t kBytes[] = {0x11, 0x22, 0x44, 0x88, 0x10, 0x55};
196 uint8_t expected = 0;
197 for (uint8_t b : kBytes) {
204 using clock = std::chrono::steady_clock;
205 auto deadline = clock::now() + std::chrono::seconds(2);
207 while (clock::now() < deadline) {
208 uint64_t resp = c->accumulator.read(0);
209 got =
static_cast<uint8_t
>(resp & 0xff);
212 std::this_thread::sleep_for(std::chrono::milliseconds(5));
215 throw std::runtime_error(
216 "typed_write_channel_byte: accumulator mismatch (expected 0x" +
217 toHex(
static_cast<uint64_t
>(expected)) +
", got 0x" +
218 toHex(
static_cast<uint64_t
>(got)) +
")");
219 std::cout <<
"typed_write_channel_byte ok (acc=0x"
220 <<
toHex(
static_cast<uint64_t
>(expected)) <<
")\n";
228 esi_system::MmioReadWrite mod(
findInst(accel,
"mmio_read_write_inst"));
229 auto c = mod.connect();
233 constexpr uint64_t kToken = 0xA5A51234'56789ABCULL;
234 c->region.write(0x10, kToken);
235 uint64_t got = c->region.read(0x10);
237 throw std::runtime_error(
"mmio_read_write: round-trip mismatch (wrote 0x" +
238 toHex(kToken) +
", read 0x" +
toHex(got) +
")");
239 std::cout <<
"mmio_read_write ok (round-trip 0x" <<
toHex(kToken) <<
")\n";
247 esi_system::TelemetryMetric mod(
findInst(accel,
"telemetry_metric_inst"));
248 auto c = mod.connect();
250 uint64_t first = c->cycleCount.readInt();
253 std::this_thread::sleep_for(std::chrono::milliseconds(50));
254 uint64_t second = c->cycleCount.readInt();
257 throw std::runtime_error(
258 "telemetry_metric: counter did not advance (first=" +
259 std::to_string(first) +
", second=" + std::to_string(second) +
")");
260 std::cout <<
"telemetry_metric ok (advanced by " << (second - first) <<
")\n";
272 esi_system::IndexedFuncGroup mod(
findInst(accel,
"indexed_func_group_inst"));
273 auto c = mod.connect();
274 constexpr size_t kN = esi_system::IndexedFuncGroup::num_entries;
275 for (uint32_t idx = 0; idx < kN; ++idx) {
276 constexpr uint16_t kArg = 100;
277 uint16_t got = c->call[idx](kArg).get();
278 uint16_t expected =
static_cast<uint16_t
>(kArg + (idx + 1));
280 throw std::runtime_error(
"indexed_func_group[" + std::to_string(idx) +
281 "]: expected " + std::to_string(expected) +
282 ", got " + std::to_string(got));
284 std::cout <<
"indexed_func_group ok (" << kN <<
" entries)\n";
300 throw std::runtime_error(
"custom_service_decl_channel[" +
301 std::to_string(idx) +
"]: instance not found");
302 esi_system::CustomServiceDeclChannel mod(it->second);
303 auto c = mod.connect();
313 uint8_t sendVal =
static_cast<uint8_t
>(0x40 + idx);
315 std::unique_ptr<uint8_t> got = fromHw.
read();
316 if (!got || *got != sendVal)
317 throw std::runtime_error(
318 "custom_service_decl_channel[" + std::to_string(idx) +
319 "]: byte loopback mismatch (sent 0x" +
320 toHex(
static_cast<uint64_t
>(sendVal)) +
", got 0x" +
321 toHex(
static_cast<uint64_t
>(got ? *got : 0u)) +
")");
323 std::cout <<
"custom_service_decl_channel_" << idx <<
" ok (byte 0x"
324 <<
toHex(
static_cast<uint64_t
>(sendVal)) <<
")\n";
341 esi_system::TypedFuncStruct mod(
findInst(accel,
"typed_func_struct_inst"));
342 auto c = mod.connect();
344 esi_system::StructArgs arg(0x1234,
static_cast<int8_t
>(-7));
345 esi_system::StructResult res = c->call(arg).get();
346 int8_t expectedX =
static_cast<int8_t
>(arg.b + 1);
347 if (res.x != expectedX || res.y != arg.b)
348 throw std::runtime_error(
349 "typed_func_struct: wrong result (b=" + std::to_string(arg.b) +
350 " x=" + std::to_string(res.x) +
" y=" + std::to_string(res.y) +
")");
351 std::cout <<
"typed_func_struct ok (b=" << (int)arg.b
352 <<
" -> x=" << (
int)res.x <<
" y=" << (int)res.y <<
")\n";
360 esi_system::TypedFuncNestedStruct mod(
361 findInst(accel,
"typed_func_nested_struct_inst"));
362 auto c = mod.connect();
364 esi_system::OddStruct arg;
366 arg.b =
static_cast<int8_t
>(-17);
368 arg.inner.q =
static_cast<int8_t
>(-7);
372 esi_system::OddStruct res = c->call(arg).get();
373 uint16_t expA =
static_cast<uint16_t
>(arg.a + 1);
374 int8_t expB =
static_cast<int8_t
>(arg.b - 3);
375 uint8_t expP =
static_cast<uint8_t
>(arg.inner.p + 5);
376 int8_t expQ =
static_cast<int8_t
>(arg.inner.q + 2);
377 uint8_t expR0 =
static_cast<uint8_t
>(arg.inner.r[0] + 1);
378 uint8_t expR1 =
static_cast<uint8_t
>(arg.inner.r[1] + 2);
379 if (res.a != expA || res.b != expB || res.inner.p != expP ||
380 res.inner.q != expQ || res.inner.r[0] != expR0 || res.inner.r[1] != expR1)
381 throw std::runtime_error(
"typed_func_nested_struct: result mismatch");
382 std::cout <<
"typed_func_nested_struct ok (a=" << res.a <<
" b=" << (int)res.b
383 <<
" p=" << (
int)res.inner.p <<
" q=" << (int)res.inner.q <<
" r=["
384 << (
int)res.inner.r[0] <<
"," << (int)res.inner.r[1] <<
"])\n";
393 esi_system::TypedFuncSubByteSigned mod(
394 findInst(accel,
"typed_func_subbyte_signed_inst"));
395 auto c = mod.connect();
397 for (int8_t arg : {
static_cast<int8_t
>(5),
static_cast<int8_t
>(-3),
398 static_cast<int8_t
>(-8),
static_cast<int8_t
>(7)}) {
399 int8_t got = c->call(arg).get();
401 throw std::runtime_error(
402 "typed_func_subbyte_signed: arg=" + std::to_string(arg) +
403 " got=" + std::to_string(got));
405 std::cout <<
"typed_func_subbyte_signed ok (4 values)\n";
413 esi_system::TypedFuncArrayResult mod(
414 findInst(accel,
"typed_func_array_result_inst"));
415 auto c = mod.connect();
417 esi_system::TypedFuncArrayResult::callArgs arg{
static_cast<int8_t
>(-3)};
418 esi_system::ArrayResult res = c->call(arg).get();
421 int8_t expect0 = arg[0];
422 int8_t expect1 =
static_cast<int8_t
>(arg[0] + 1);
423 bool ok = (a == expect0 && b == expect1) || (a == expect1 && b == expect0);
425 throw std::runtime_error(
"typed_func_array_result: result mismatch");
426 std::cout <<
"typed_func_array_result ok ([" << (int)a <<
"," << (
int)b
438 esi_system::TypedFuncWindowedList mod(
439 findInst(accel,
"typed_func_windowed_list_inst"));
440 auto c = mod.connect();
442 using ArgT = esi_system::TypedFuncWindowedList::callArgs;
443 using ResT = esi_system::TypedFuncWindowedList::callResult;
444 std::vector<esi_system::TransformListItem> input;
445 for (uint32_t v : {3u, 5u, 7u, 9u, 11u})
446 input.emplace_back(v);
449 ResT result = c->call(arg).get();
451 if (result.data_count() != input.size())
452 throw std::runtime_error(
453 "typed_func_windowed_list: wrong result size (got " +
454 std::to_string(result.data_count()) +
")");
456 for (
const esi_system::TransformListItem &item : result.data()) {
457 uint32_t expected = input[i].v + input[i].v;
458 if (item.v != expected)
459 throw std::runtime_error(
"typed_func_windowed_list: element " +
460 std::to_string(i) +
" expected " +
461 std::to_string(expected) +
", got " +
462 std::to_string(item.v));
465 std::cout <<
"typed_func_windowed_list ok (" << input.size()
466 <<
" items doubled)\n";
475 esi_system::ChannelWindowedListRead mod(
476 findInst(accel,
"channel_windowed_list_read_inst"));
477 auto c = mod.connect();
479 using WinT = esi_system::ChannelWindowedListRead::dataData;
483 c->trigger.write(0x10, 0u);
485 std::unique_ptr<WinT> got = c->data.read();
487 throw std::runtime_error(
"channel_windowed_list_read: null read result");
489 static constexpr uint16_t kTag = 0xCAFE;
490 static const uint32_t kExpected[] = {10u, 20u, 30u, 40u};
491 if (got->tag() != kTag)
492 throw std::runtime_error(
493 "channel_windowed_list_read: wrong tag, expected 0x" +
494 toHex(
static_cast<uint64_t
>(kTag)) +
" got 0x" +
495 toHex(
static_cast<uint64_t
>(got->tag())));
496 if (got->items_count() != 4)
497 throw std::runtime_error(
498 "channel_windowed_list_read: wrong item count, expected 4 got " +
499 std::to_string(got->items_count()));
501 for (uint32_t v : got->items()) {
502 if (v != kExpected[i])
503 throw std::runtime_error(
"channel_windowed_list_read: element " +
504 std::to_string(i) +
" expected " +
505 std::to_string(kExpected[i]) +
" got " +
509 std::cout <<
"channel_windowed_list_read ok (tag=0x"
510 <<
toHex(
static_cast<uint64_t
>(kTag)) <<
", items=[10,20,30,40])\n";
521 esi_system::ChannelWindowedListWrite mod(
522 findInst(accel,
"channel_windowed_list_write_inst"));
523 auto c = mod.connect();
525 using WinT = esi_system::ChannelWindowedListWrite::dataData;
527 static constexpr uint16_t kTag = 0xCAFE;
528 std::vector<uint32_t> items{10u, 20u, 30u, 40u};
529 c->data.write(WinT(kTag, items));
533 using clock = std::chrono::steady_clock;
534 auto deadline = clock::now() + std::chrono::seconds(5);
536 while (clock::now() < deadline) {
537 match = c->match.read(0);
540 std::this_thread::sleep_for(std::chrono::milliseconds(5));
543 throw std::runtime_error(
544 "channel_windowed_list_write: HW did not report a match within "
547 std::cout <<
"channel_windowed_list_write ok (tag=0x"
548 <<
toHex(
static_cast<uint64_t
>(kTag)) <<
", items=[10,20,30,40])\n";
559 esi_system::CallbackWindowedList mod(
560 findInst(accel,
"callback_windowed_list_inst"));
561 auto c = mod.connect();
563 using WinT = esi_system::CallbackWindowedList::callbackArgs;
565 std::atomic<bool> got_call(
false);
566 std::string error_msg;
567 std::mutex error_mtx;
568 c->callback.connect([&](
const WinT &arg) {
570 static constexpr uint16_t kTag = 0xCAFE;
571 static const uint32_t kExpected[] = {10u, 20u, 30u, 40u};
572 if (arg.tag() != kTag)
573 throw std::runtime_error(
574 "callback_windowed_list: wrong tag, expected 0x" +
575 toHex(
static_cast<uint64_t
>(kTag)) +
" got 0x" +
576 toHex(
static_cast<uint64_t
>(arg.tag())));
577 if (arg.items_count() != 4)
578 throw std::runtime_error(
579 "callback_windowed_list: wrong item count, expected 4 got " +
580 std::to_string(arg.items_count()));
582 for (uint32_t v : arg.items()) {
583 if (v != kExpected[i])
584 throw std::runtime_error(
"callback_windowed_list: element " +
585 std::to_string(i) +
" expected " +
586 std::to_string(kExpected[i]) +
" got " +
591 std::cout <<
"callback_windowed_list ok (tag=0x"
592 <<
toHex(
static_cast<uint64_t
>(kTag))
593 <<
", items=[10,20,30,40])\n";
594 }
catch (
const std::exception &e) {
595 std::lock_guard<std::mutex> lk(error_mtx);
596 error_msg = e.what();
598 got_call.store(
true, std::memory_order_release);
602 c->trigger.write(0x10, 0u);
604 using clock = std::chrono::steady_clock;
605 auto deadline = clock::now() + std::chrono::seconds(5);
606 while (!got_call.load(std::memory_order_acquire) && clock::now() < deadline)
607 std::this_thread::sleep_for(std::chrono::milliseconds(10));
608 if (!got_call.load(std::memory_order_acquire))
609 throw std::runtime_error(
610 "callback_windowed_list: callback did not fire within timeout");
611 std::lock_guard<std::mutex> lk(error_mtx);
612 if (!error_msg.empty())
613 throw std::runtime_error(error_msg);
619 "Per-port-kind coverage tests for ESI runtime + facade codegen. "
620 "Run a single probe with --probe NAME or run all probes (in registry "
621 "order) by omitting the flag.",
Top level accelerator class.
Represents either the top level or an instance of a hardware module.
const std::map< AppID, Instance * > & getChildren() const
Access the module's children by ID.
Strongly typed wrapper around a raw read channel.
std::unique_ptr< T > read()
Blocking typed read in polling mode.
void connect(const ChannelPort::ConnectOptions &opts={std::nullopt, false})
Connect in polling mode.
void connect(const ChannelPort::ConnectOptions &opts={std::nullopt, false})
void write(const T &data)
std::string toHex(void *val)
#define ESI_PROBE_REGISTRY(name, description,...)
Convenience macro: defines main() with a probe registry.
static int runCustomServiceDeclChannel0(Accelerator *accel)
static int runTypedFuncWindowedList(Accelerator *accel)
static int runChannelWindowedListRead(Accelerator *accel)
static int runMmioReadWrite(Accelerator *accel)
static int runTypedReadChannelStruct(Accelerator *accel)
static int runTypedFuncVoidResult(Accelerator *accel)
static int runCustomServiceDeclChannel(Accelerator *accel, uint32_t idx)
static int runTypedFuncSubByteSigned(Accelerator *accel)
static esi::HWModule * findInst(Accelerator *accel, const char *appidName)
static int runCallServiceCallback(Accelerator *accel)
static int runTypedFuncArrayResult(Accelerator *accel)
static int runCallbackWindowedList(Accelerator *accel)
static int runTypedFuncMultiArg(Accelerator *accel)
static int runTelemetryMetric(Accelerator *accel)
static int runIndexedFuncGroup(Accelerator *accel)
static int runTypedFuncVoidArg(Accelerator *accel)
static int runTypedWriteChannelByte(Accelerator *accel)
static int runCustomServiceDeclChannel1(Accelerator *accel)
static int runTypedFuncNestedStruct(Accelerator *accel)
static int runTypedFuncStruct(Accelerator *accel)
static int runChannelWindowedListWrite(Accelerator *accel)