CIRCT 24.0.0git
Loading...
Searching...
No Matches
test_loopback_cpp.py
Go to the documentation of this file.
1# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
2# See https://llvm.org/LICENSE.txt for license information.
3# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
5from __future__ import annotations
6
7import os
8from pathlib import Path
9import shutil
10import subprocess
11import sys
12
13# The Trace backend uses ';' as the connection-string separator on Windows.
14_TRACE_SEP = ";" if os.name == "nt" else ":"
15
16import pytest
17
18from esiaccel.cosim.pytest import cosim_test
19
20from .conftest import (HW_DIR, SW_DIR, build_cpp_test, check_lines,
21 get_runtime_root, require_tool, run_probe)
22
23LOOPBACK_PROBES = [
24 ("depth_constant", ["depth: 0x5", "depth_constant ok"]),
25 ("loopback_i8", ["loopback_i8 ok: 0x5a"]),
26 ("struct_func", ["struct_func ok: b=-7 x=-6 y=-7"]),
27 ("odd_struct_func",
28 ["odd_struct_func ok: a=2749 b=-20 p=10 q=-5 r0=4 r1=6"]),
29 ("array_func", ["array_func ok: -3 -2"]),
30 ("serial_coord_translate", ["serial_coord_translate ok"]),
31 ("serial_coord_translate_hostmem", ["serial_coord_translate_hostmem ok"]),
32]
33
34LOOPBACK_TYPED_PROBES = [
35 ("depth_constant", ["depth: 0x5", "depth_constant ok"]),
36 ("loopback_i8", ["loopback_i8 ok: 0x5a"]),
37 ("sint4_loopback", ["sint4_loopback ok: pos=5 neg=-3"]),
38 ("struct_func", ["struct_func ok: b=-7 x=-6 y=-7"]),
39 ("odd_struct_func",
40 ["odd_struct_func ok: a=2749 b=-20 p=10 q=-5 r0=4 r1=6"]),
41 ("array_func", ["array_func ok: -3 -2"]),
42 ("serial_coord_translate", ["serial_coord_translate ok"]),
43]
44
45
46def _build_loopback_codegen(tmp_path: Path, host: str, port: int) -> Path:
47 """Run live-connection codegen and build the loopback_test binary.
48
49 This test deliberately uses ``esiaccel.codegen --platform cosim`` (live
50 connection) rather than ``--file`` (offline manifest) to exercise that
51 codegen path.
52 """
53 require_tool("cmake")
54 require_tool("ninja")
55
56 runtime_root = get_runtime_root()
57
58 include_dir = tmp_path / "include"
59 generated_dir = include_dir / "loopback"
60 generated_dir.mkdir(parents=True, exist_ok=True)
61
62 subprocess.run(
63 [
64 sys.executable,
65 "-m",
66 "esiaccel.codegen",
67 "--platform",
68 "cosim",
69 "--connection",
70 f"{host}:{port}",
71 "--output-dir",
72 str(generated_dir),
73 ],
74 check=True,
75 )
76
77 # Verify generated header content (LOOPBACK-H checks).
78 header_path = generated_dir / "LoopbackIP.h"
79 assert header_path.exists(), "Generated header LoopbackIP.h not found"
80 header_content = header_path.read_text()
81 check_lines(header_content, [
82 "/// Generated header for esi_system module LoopbackIP.",
83 "#pragma once",
84 '#include "types.h"',
85 "namespace esi_system {",
86 "class LoopbackIP {",
87 "static constexpr uint32_t depth = 0x5;",
88 "} // namespace esi_system",
89 ])
90
91 build_dir = tmp_path / "loopback-build"
92 result = subprocess.run(
93 [
94 "cmake",
95 "-G",
96 "Ninja",
97 "-S",
98 str(SW_DIR),
99 "-B",
100 str(build_dir),
101 "-DCMAKE_BUILD_TYPE=Release",
102 f"-DLOOPBACK_GENERATED_DIR={include_dir}",
103 f"-DESI_RUNTIME_ROOT={runtime_root}",
104 ],
105 capture_output=True,
106 text=True,
107 )
108 assert result.returncode == 0, (
109 f"cmake configure failed (rc={result.returncode}):\n"
110 f"--- stdout ---\n{result.stdout}\n"
111 f"--- stderr ---\n{result.stderr}")
112
113 result = subprocess.run(
114 [
115 "cmake", "--build",
116 str(build_dir), "--target", "loopback_test", "--config", "Release"
117 ],
118 capture_output=True,
119 text=True,
120 )
121 assert result.returncode == 0, (
122 f"cmake build failed (rc={result.returncode}):\n"
123 f"--- stdout ---\n{result.stdout}\n"
124 f"--- stderr ---\n{result.stderr}")
125
126 return build_dir / "loopback_test"
127
128
129@cosim_test(HW_DIR / "loopback.py")
131 """Tests for esiquery against the loopback design."""
132
133 def test_esi_version(self, conn) -> None:
134 assert conn.sysinfo().esi_version() == 1
135 assert conn.get_service_mmio().read(0x10) == 1
136 assert conn.manifest().api_version == 1
137
138 def test_loopback_cpp_codegen(self, tmp_path: Path, host: str,
139 port: int) -> None:
140 """Build against live-connection codegen and run all probes."""
141 binary = _build_loopback_codegen(tmp_path, host, port)
142 for probe, expected in LOOPBACK_PROBES:
143 run_probe(binary, host, port, probe, expected)
144
145 def test_loopback_typed_cpp_codegen(self, host: str, port: int,
146 sources_dir: Path) -> None:
147 binary = build_cpp_test(sources_dir, "loopback_typed_test", "loopback")
148 for probe, expected in LOOPBACK_TYPED_PROBES:
149 run_probe(binary, host, port, probe, expected)
150
151 def test_loopback_query_info(self, sources_dir: Path) -> None:
152 """Verify esiquery info output against the generated manifest
153 (QUERY-INFO checks)."""
154 require_tool("esiquery")
155 manifest = sources_dir / "esi_system_manifest.json"
156 assert manifest.exists(), "Manifest not found"
157 result = subprocess.run(
158 ["esiquery", "trace", f"w{_TRACE_SEP}{manifest}", "info"],
159 check=True,
160 capture_output=True,
161 text=True,
162 )
163 check_lines(result.stdout, [
164 "API version: 1",
165 "* Module information",
166 "- LoopbackIP v0.0",
167 "IP which simply echos bytes",
168 "Constants:",
169 "depth: 5",
170 "Extra metadata:",
171 "foo: 1",
172 ])
173
174 def test_loopback_query_hier(self, sources_dir: Path) -> None:
175 """Verify esiquery hier output against the generated manifest
176 (QUERY-HIER checks)."""
177 require_tool("esiquery")
178 manifest = sources_dir / "esi_system_manifest.json"
179 assert manifest.exists(), "Manifest not found"
180 result = subprocess.run(
181 ["esiquery", "trace", f"w{_TRACE_SEP}{manifest}", "hier"],
182 check=True,
183 capture_output=True,
184 text=True,
185 )
186 check_lines(result.stdout, [
187 "* Design hierarchy",
188 "func1: function uint16(uint16)",
189 "structFunc: function ResultStruct(ArgStruct)",
190 "arrayFunc: function ResultArray(sint8[1])",
191 "* Instance: loopback_inst[0]",
192 "loopback_tohw:",
193 "recv: bits8",
194 "loopback_fromhw:",
195 "send: bits8",
196 "mysvc_recv:",
197 "recv: void",
198 "mysvc_send:",
199 "send: void",
200 "* Instance: loopback_inst[1]",
201 ])
None test_loopback_typed_cpp_codegen(self, str host, int port, Path sources_dir)
None test_loopback_cpp_codegen(self, Path tmp_path, str host, int port)
Path _build_loopback_codegen(Path tmp_path, str host, int port)