esiaccel 0.0.17.dev735__cp311-cp311-win_amd64.whl → 0.1.1__cp311-cp311-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of esiaccel might be problematic. Click here for more details.
- esiaccel/CosimBackend.dll +0 -0
- esiaccel/CosimBackend.lib +0 -0
- esiaccel/ESICppRuntime.dll +0 -0
- esiaccel/ESICppRuntime.lib +0 -0
- esiaccel/bin/esi-cosim.py +405 -0
- esiaccel/bin/esiquery.exe +0 -0
- esiaccel/cmake/esiaccelConfig.cmake +1 -1
- esiaccel/cosim/Cosim_DpiPkg.sv +85 -0
- esiaccel/cosim/Cosim_Endpoint.sv +189 -0
- esiaccel/cosim/Cosim_Manifest.sv +32 -0
- esiaccel/cosim/driver.cpp +131 -0
- esiaccel/cosim/driver.sv +60 -0
- esiaccel/esiCppAccel.cp311-win_amd64.pyd +0 -0
- esiaccel/include/esi/CLI.h +9 -3
- esiaccel/include/esi/Engines.h +124 -0
- esiaccel/include/esi/Logging.h +43 -7
- esiaccel/include/esi/Services.h +44 -0
- esiaccel/include/esi/backends/Cosim.h +85 -0
- esiaccel/include/esi/backends/RpcServer.h +55 -0
- esiaccel/lib/EsiCosimDpiServer.dll +0 -0
- esiaccel/lib/EsiCosimDpiServer.lib +0 -0
- esiaccel/lib/MtiPli.dll +0 -0
- esiaccel/lib/MtiPli.lib +0 -0
- esiaccel/types.py +55 -0
- esiaccel/zlib1.dll +0 -0
- {esiaccel-0.0.17.dev735.dist-info → esiaccel-0.1.1.dist-info}/METADATA +3 -3
- esiaccel-0.1.1.dist-info/RECORD +44 -0
- {esiaccel-0.0.17.dev735.dist-info → esiaccel-0.1.1.dist-info}/WHEEL +1 -1
- esiaccel-0.0.17.dev735.dist-info/RECORD +0 -29
- {esiaccel-0.0.17.dev735.dist-info → esiaccel-0.1.1.dist-info}/entry_points.txt +0 -0
- {esiaccel-0.0.17.dev735.dist-info → esiaccel-0.1.1.dist-info/licenses}/LICENSE +0 -0
- {esiaccel-0.0.17.dev735.dist-info → esiaccel-0.1.1.dist-info}/top_level.txt +0 -0
|
Binary file
|
|
Binary file
|
esiaccel/ESICppRuntime.dll
CHANGED
|
Binary file
|
esiaccel/ESICppRuntime.lib
CHANGED
|
Binary file
|
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
# ===- esi-cosim.py - ESI cosimulation launch utility --------*- python -*-===//
|
|
4
|
+
#
|
|
5
|
+
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
6
|
+
# See https://llvm.org/LICENSE.txt for license information.
|
|
7
|
+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
8
|
+
#
|
|
9
|
+
# ===----------------------------------------------------------------------===//
|
|
10
|
+
#
|
|
11
|
+
# Utility script to start a simulation and launch a command to interact with it
|
|
12
|
+
# via ESI cosimulation.
|
|
13
|
+
#
|
|
14
|
+
# ===----------------------------------------------------------------------===//
|
|
15
|
+
|
|
16
|
+
import argparse
|
|
17
|
+
import os
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
import re
|
|
20
|
+
import signal
|
|
21
|
+
import socket
|
|
22
|
+
import subprocess
|
|
23
|
+
import sys
|
|
24
|
+
import textwrap
|
|
25
|
+
import time
|
|
26
|
+
from typing import Dict, List
|
|
27
|
+
|
|
28
|
+
_thisdir = Path(__file__).parent
|
|
29
|
+
CosimCollateralDir = _thisdir.parent / "cosim"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def is_port_open(port) -> bool:
|
|
33
|
+
"""Check if a TCP port is open locally."""
|
|
34
|
+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
35
|
+
result = sock.connect_ex(('127.0.0.1', port))
|
|
36
|
+
sock.close()
|
|
37
|
+
return True if result == 0 else False
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class SourceFiles:
|
|
41
|
+
|
|
42
|
+
def __init__(self, top: str) -> None:
|
|
43
|
+
# User source files.
|
|
44
|
+
self.user: List[Path] = []
|
|
45
|
+
# DPI shared objects.
|
|
46
|
+
self.dpi_so: List[str] = ["EsiCosimDpiServer"]
|
|
47
|
+
# DPI SV files.
|
|
48
|
+
self.dpi_sv: List[Path] = [
|
|
49
|
+
CosimCollateralDir / "Cosim_DpiPkg.sv",
|
|
50
|
+
CosimCollateralDir / "Cosim_Endpoint.sv",
|
|
51
|
+
CosimCollateralDir / "Cosim_Manifest.sv",
|
|
52
|
+
]
|
|
53
|
+
# Name of the top module.
|
|
54
|
+
self.top = top
|
|
55
|
+
|
|
56
|
+
def add_dir(self, dir: Path):
|
|
57
|
+
"""Add all the RTL files in a directory to the source list."""
|
|
58
|
+
for file in sorted(dir.iterdir()):
|
|
59
|
+
if file.is_file() and (file.suffix == ".sv" or file.suffix == ".v"):
|
|
60
|
+
self.user.append(file)
|
|
61
|
+
elif file.is_dir():
|
|
62
|
+
self.add_dir(file)
|
|
63
|
+
|
|
64
|
+
def dpi_so_paths(self) -> List[Path]:
|
|
65
|
+
"""Return a list of all the DPI shared object files."""
|
|
66
|
+
|
|
67
|
+
def find_so(name: str) -> Path:
|
|
68
|
+
for path in Simulator.get_env().get("LD_LIBRARY_PATH", "").split(":"):
|
|
69
|
+
if os.name == "nt":
|
|
70
|
+
so = Path(path) / f"{name}.dll"
|
|
71
|
+
else:
|
|
72
|
+
so = Path(path) / f"lib{name}.so"
|
|
73
|
+
if so.exists():
|
|
74
|
+
return so
|
|
75
|
+
raise FileNotFoundError(f"Could not find {name}.so in LD_LIBRARY_PATH")
|
|
76
|
+
|
|
77
|
+
return [find_so(name) for name in self.dpi_so]
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def rtl_sources(self) -> List[Path]:
|
|
81
|
+
"""Return a list of all the RTL source files."""
|
|
82
|
+
return self.dpi_sv + self.user
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class Simulator:
|
|
86
|
+
|
|
87
|
+
# Some RTL simulators don't use stderr for error messages. Everything goes to
|
|
88
|
+
# stdout. Boo! They should feel bad about this. Also, they can specify that
|
|
89
|
+
# broken behavior by overriding this.
|
|
90
|
+
UsesStderr = True
|
|
91
|
+
|
|
92
|
+
def __init__(self, sources: SourceFiles, run_dir: Path, debug: bool):
|
|
93
|
+
self.sources = sources
|
|
94
|
+
self.run_dir = run_dir
|
|
95
|
+
self.debug = debug
|
|
96
|
+
|
|
97
|
+
@staticmethod
|
|
98
|
+
def get_env() -> Dict[str, str]:
|
|
99
|
+
"""Get the environment variables to locate shared objects."""
|
|
100
|
+
|
|
101
|
+
env = os.environ.copy()
|
|
102
|
+
env["LIBRARY_PATH"] = env.get("LIBRARY_PATH", "") + ":" + str(
|
|
103
|
+
_thisdir.parent / "lib")
|
|
104
|
+
env["LD_LIBRARY_PATH"] = env.get("LD_LIBRARY_PATH", "") + ":" + str(
|
|
105
|
+
_thisdir.parent / "lib")
|
|
106
|
+
return env
|
|
107
|
+
|
|
108
|
+
def compile_commands(self) -> List[List[str]]:
|
|
109
|
+
"""Compile the sources. Returns the exit code of the simulation compiler."""
|
|
110
|
+
assert False, "Must be implemented by subclass"
|
|
111
|
+
|
|
112
|
+
def compile(self) -> int:
|
|
113
|
+
cmds = self.compile_commands()
|
|
114
|
+
self.run_dir.mkdir(parents=True, exist_ok=True)
|
|
115
|
+
with (self.run_dir / "compile_stdout.log").open("w") as stdout, (
|
|
116
|
+
self.run_dir / "compile_stderr.log").open("w") as stderr:
|
|
117
|
+
for cmd in cmds:
|
|
118
|
+
stderr.write(" ".join(cmd) + "\n")
|
|
119
|
+
cp = subprocess.run(cmd,
|
|
120
|
+
env=Simulator.get_env(),
|
|
121
|
+
capture_output=True,
|
|
122
|
+
text=True)
|
|
123
|
+
stdout.write(cp.stdout)
|
|
124
|
+
stderr.write(cp.stderr)
|
|
125
|
+
if cp.returncode != 0:
|
|
126
|
+
print("====== Compilation failure:")
|
|
127
|
+
if self.UsesStderr:
|
|
128
|
+
print(cp.stderr)
|
|
129
|
+
else:
|
|
130
|
+
print(cp.stdout)
|
|
131
|
+
return cp.returncode
|
|
132
|
+
return 0
|
|
133
|
+
|
|
134
|
+
def run_command(self, gui: bool) -> List[str]:
|
|
135
|
+
"""Return the command to run the simulation."""
|
|
136
|
+
assert False, "Must be implemented by subclass"
|
|
137
|
+
|
|
138
|
+
def run(self, inner_command: str, gui: bool = False) -> int:
|
|
139
|
+
"""Start the simulation then run the command specified. Kill the simulation
|
|
140
|
+
when the command exits."""
|
|
141
|
+
|
|
142
|
+
# 'simProc' is accessed in the finally block. Declare it here to avoid
|
|
143
|
+
# syntax errors in that block.
|
|
144
|
+
simProc = None
|
|
145
|
+
try:
|
|
146
|
+
# Open log files
|
|
147
|
+
self.run_dir.mkdir(parents=True, exist_ok=True)
|
|
148
|
+
simStdout = open(self.run_dir / "sim_stdout.log", "w")
|
|
149
|
+
simStderr = open(self.run_dir / "sim_stderr.log", "w")
|
|
150
|
+
|
|
151
|
+
# Erase the config file if it exists. We don't want to read
|
|
152
|
+
# an old config.
|
|
153
|
+
portFileName = self.run_dir / "cosim.cfg"
|
|
154
|
+
if os.path.exists(portFileName):
|
|
155
|
+
os.remove(portFileName)
|
|
156
|
+
|
|
157
|
+
# Run the simulation.
|
|
158
|
+
simEnv = Simulator.get_env()
|
|
159
|
+
if self.debug:
|
|
160
|
+
simEnv["COSIM_DEBUG_FILE"] = "cosim_debug.log"
|
|
161
|
+
if "DEBUG_PERIOD" not in simEnv:
|
|
162
|
+
# Slow the simulation down to one tick per millisecond.
|
|
163
|
+
simEnv["DEBUG_PERIOD"] = "1"
|
|
164
|
+
simProc = subprocess.Popen(self.run_command(gui),
|
|
165
|
+
stdout=simStdout,
|
|
166
|
+
stderr=simStderr,
|
|
167
|
+
env=simEnv,
|
|
168
|
+
cwd=self.run_dir,
|
|
169
|
+
preexec_fn=os.setsid)
|
|
170
|
+
simStderr.close()
|
|
171
|
+
simStdout.close()
|
|
172
|
+
|
|
173
|
+
# Get the port which the simulation RPC selected.
|
|
174
|
+
checkCount = 0
|
|
175
|
+
while (not os.path.exists(portFileName)) and \
|
|
176
|
+
simProc.poll() is None:
|
|
177
|
+
time.sleep(0.1)
|
|
178
|
+
checkCount += 1
|
|
179
|
+
if checkCount > 200 and not gui:
|
|
180
|
+
raise Exception(f"Cosim never wrote cfg file: {portFileName}")
|
|
181
|
+
port = -1
|
|
182
|
+
while port < 0:
|
|
183
|
+
portFile = open(portFileName, "r")
|
|
184
|
+
for line in portFile.readlines():
|
|
185
|
+
m = re.match("port: (\\d+)", line)
|
|
186
|
+
if m is not None:
|
|
187
|
+
port = int(m.group(1))
|
|
188
|
+
portFile.close()
|
|
189
|
+
|
|
190
|
+
# Wait for the simulation to start accepting RPC connections.
|
|
191
|
+
checkCount = 0
|
|
192
|
+
while not is_port_open(port):
|
|
193
|
+
checkCount += 1
|
|
194
|
+
if checkCount > 200:
|
|
195
|
+
raise Exception(f"Cosim RPC port ({port}) never opened")
|
|
196
|
+
if simProc.poll() is not None:
|
|
197
|
+
raise Exception("Simulation exited early")
|
|
198
|
+
time.sleep(0.05)
|
|
199
|
+
|
|
200
|
+
# Run the inner command, passing the connection info via environment vars.
|
|
201
|
+
testEnv = os.environ.copy()
|
|
202
|
+
testEnv["ESI_COSIM_PORT"] = str(port)
|
|
203
|
+
testEnv["ESI_COSIM_HOST"] = "localhost"
|
|
204
|
+
return subprocess.run(inner_command, cwd=os.getcwd(),
|
|
205
|
+
env=testEnv).returncode
|
|
206
|
+
finally:
|
|
207
|
+
# Make sure to stop the simulation no matter what.
|
|
208
|
+
if simProc:
|
|
209
|
+
os.killpg(os.getpgid(simProc.pid), signal.SIGINT)
|
|
210
|
+
# Allow the simulation time to flush its outputs.
|
|
211
|
+
try:
|
|
212
|
+
simProc.wait(timeout=1.0)
|
|
213
|
+
except subprocess.TimeoutExpired:
|
|
214
|
+
# If the simulation doesn't exit of its own free will, kill it.
|
|
215
|
+
simProc.kill()
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
class Verilator(Simulator):
|
|
219
|
+
"""Run and compile funcs for Verilator."""
|
|
220
|
+
|
|
221
|
+
DefaultDriver = CosimCollateralDir / "driver.cpp"
|
|
222
|
+
|
|
223
|
+
def __init__(self, sources: SourceFiles, run_dir: Path, debug: bool):
|
|
224
|
+
super().__init__(sources, run_dir, debug)
|
|
225
|
+
|
|
226
|
+
self.verilator = "verilator"
|
|
227
|
+
if "VERILATOR_PATH" in os.environ:
|
|
228
|
+
self.verilator = os.environ["VERILATOR_PATH"]
|
|
229
|
+
|
|
230
|
+
def compile_commands(self) -> List[List[str]]:
|
|
231
|
+
cmd: List[str] = [
|
|
232
|
+
self.verilator,
|
|
233
|
+
"--cc",
|
|
234
|
+
"--top-module",
|
|
235
|
+
self.sources.top,
|
|
236
|
+
"-DSIMULATION",
|
|
237
|
+
"-Wno-TIMESCALEMOD",
|
|
238
|
+
"-Wno-fatal",
|
|
239
|
+
"-sv",
|
|
240
|
+
"--build",
|
|
241
|
+
"--exe",
|
|
242
|
+
"--assert",
|
|
243
|
+
str(Verilator.DefaultDriver),
|
|
244
|
+
]
|
|
245
|
+
cflags = [
|
|
246
|
+
"-DTOP_MODULE=" + self.sources.top,
|
|
247
|
+
]
|
|
248
|
+
if self.debug:
|
|
249
|
+
cmd += [
|
|
250
|
+
"--trace", "--trace-params", "--trace-structs", "--trace-underscore"
|
|
251
|
+
]
|
|
252
|
+
cflags.append("-DTRACE")
|
|
253
|
+
if len(cflags) > 0:
|
|
254
|
+
cmd += ["-CFLAGS", " ".join(cflags)]
|
|
255
|
+
if len(self.sources.dpi_so) > 0:
|
|
256
|
+
cmd += ["-LDFLAGS", " ".join(["-l" + so for so in self.sources.dpi_so])]
|
|
257
|
+
cmd += [str(p) for p in self.sources.rtl_sources]
|
|
258
|
+
return [cmd]
|
|
259
|
+
|
|
260
|
+
def run_command(self, gui: bool):
|
|
261
|
+
if gui:
|
|
262
|
+
raise RuntimeError("Verilator does not support GUI mode.")
|
|
263
|
+
exe = Path.cwd() / "obj_dir" / ("V" + self.sources.top)
|
|
264
|
+
return [str(exe)]
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
class Questa(Simulator):
|
|
268
|
+
"""Run and compile funcs for Questasim."""
|
|
269
|
+
|
|
270
|
+
DefaultDriver = CosimCollateralDir / "driver.sv"
|
|
271
|
+
|
|
272
|
+
# Questa doesn't use stderr for error messages. Everything goes to stdout.
|
|
273
|
+
UsesStderr = False
|
|
274
|
+
|
|
275
|
+
def internal_compile_commands(self) -> List[str]:
|
|
276
|
+
cmds = [
|
|
277
|
+
"onerror { quit -f -code 1 }",
|
|
278
|
+
]
|
|
279
|
+
sources = self.sources.rtl_sources
|
|
280
|
+
sources.append(Questa.DefaultDriver)
|
|
281
|
+
for src in sources:
|
|
282
|
+
cmds.append(f"vlog -incr +acc -sv +define+TOP_MODULE={self.sources.top}"
|
|
283
|
+
f" +define+SIMULATION {str(src)}")
|
|
284
|
+
cmds.append(f"vopt -incr driver -o driver_opt +acc")
|
|
285
|
+
return cmds
|
|
286
|
+
|
|
287
|
+
def compile_commands(self) -> List[List[str]]:
|
|
288
|
+
with open("compile.do", "w") as f:
|
|
289
|
+
for cmd in self.internal_compile_commands():
|
|
290
|
+
f.write(cmd)
|
|
291
|
+
f.write("\n")
|
|
292
|
+
f.write("quit\n")
|
|
293
|
+
return [
|
|
294
|
+
["vsim", "-batch", "-do", "compile.do"],
|
|
295
|
+
]
|
|
296
|
+
|
|
297
|
+
def run_command(self, gui: bool) -> List[str]:
|
|
298
|
+
vsim = "vsim"
|
|
299
|
+
# Note: vsim exit codes say nothing about the test run's pass/fail even
|
|
300
|
+
# if $fatal is encountered in the simulation.
|
|
301
|
+
if gui:
|
|
302
|
+
cmd = [
|
|
303
|
+
vsim,
|
|
304
|
+
"driver_opt",
|
|
305
|
+
]
|
|
306
|
+
else:
|
|
307
|
+
cmd = [
|
|
308
|
+
vsim,
|
|
309
|
+
"driver_opt",
|
|
310
|
+
"-batch",
|
|
311
|
+
"-do",
|
|
312
|
+
"run -all",
|
|
313
|
+
]
|
|
314
|
+
for lib in self.sources.dpi_so_paths():
|
|
315
|
+
svLib = os.path.splitext(lib)[0]
|
|
316
|
+
cmd.append("-sv_lib")
|
|
317
|
+
cmd.append(svLib)
|
|
318
|
+
return cmd
|
|
319
|
+
|
|
320
|
+
def run(self, inner_command: str, gui: bool = False) -> int:
|
|
321
|
+
"""Override the Simulator.run() to add a soft link in the run directory (to
|
|
322
|
+
the work directory) before running vsim the usual way."""
|
|
323
|
+
|
|
324
|
+
# Create a soft link to the work directory.
|
|
325
|
+
workDir = self.run_dir / "work"
|
|
326
|
+
if not workDir.exists():
|
|
327
|
+
os.symlink(Path(os.getcwd()) / "work", workDir)
|
|
328
|
+
|
|
329
|
+
# Run the simulation.
|
|
330
|
+
return super().run(inner_command, gui)
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
def __main__(args):
|
|
334
|
+
argparser = argparse.ArgumentParser(
|
|
335
|
+
description="Wrap a 'inner_cmd' in an ESI cosimulation environment.",
|
|
336
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
337
|
+
epilog=textwrap.dedent("""
|
|
338
|
+
Notes:
|
|
339
|
+
- For Verilator, libEsiCosimDpiServer.so must be in the dynamic
|
|
340
|
+
library runtime search path (LD_LIBRARY_PATH) and link time path
|
|
341
|
+
(LIBRARY_PATH). If it is installed to a standard location (e.g.
|
|
342
|
+
/usr/lib), this should be handled automatically.
|
|
343
|
+
- This script needs to sit in the same directory as the ESI support
|
|
344
|
+
SystemVerilog (e.g. Cosim_DpiPkg.sv, Cosim_MMIO.sv, etc.). It can,
|
|
345
|
+
however, be soft linked to a different location.
|
|
346
|
+
- The simulator executable(s) must be in your PATH.
|
|
347
|
+
"""))
|
|
348
|
+
|
|
349
|
+
argparser.add_argument(
|
|
350
|
+
"--sim",
|
|
351
|
+
type=str,
|
|
352
|
+
default="verilator",
|
|
353
|
+
help="Name of the RTL simulator to use or path to an executable.")
|
|
354
|
+
argparser.add_argument("--rundir",
|
|
355
|
+
default="run",
|
|
356
|
+
help="Directory in which simulation should be run.")
|
|
357
|
+
argparser.add_argument(
|
|
358
|
+
"--top",
|
|
359
|
+
default="ESI_Cosim_Top",
|
|
360
|
+
help="Name of the 'top' module to use in the simulation.")
|
|
361
|
+
argparser.add_argument("--no-compile",
|
|
362
|
+
action="store_true",
|
|
363
|
+
help="Do not run the compile.")
|
|
364
|
+
argparser.add_argument("--debug",
|
|
365
|
+
action="store_true",
|
|
366
|
+
help="Enable debug output.")
|
|
367
|
+
argparser.add_argument("--gui",
|
|
368
|
+
action="store_true",
|
|
369
|
+
help="Run the simulator in GUI mode (if supported).")
|
|
370
|
+
argparser.add_argument("--source",
|
|
371
|
+
help="Directories containing the source files.",
|
|
372
|
+
default="hw")
|
|
373
|
+
|
|
374
|
+
argparser.add_argument("inner_cmd",
|
|
375
|
+
nargs=argparse.REMAINDER,
|
|
376
|
+
help="Command to run in the simulation environment.")
|
|
377
|
+
|
|
378
|
+
if len(args) <= 1:
|
|
379
|
+
argparser.print_help()
|
|
380
|
+
return
|
|
381
|
+
args = argparser.parse_args(args[1:])
|
|
382
|
+
|
|
383
|
+
sources = SourceFiles(args.top)
|
|
384
|
+
sources.add_dir(Path(args.source))
|
|
385
|
+
|
|
386
|
+
if args.sim == "verilator":
|
|
387
|
+
sim = Verilator(sources, Path(args.rundir), args.debug)
|
|
388
|
+
elif args.sim == "questa":
|
|
389
|
+
sim = Questa(sources, Path(args.rundir), args.debug)
|
|
390
|
+
else:
|
|
391
|
+
print("Unknown simulator: " + args.sim)
|
|
392
|
+
print("Supported simulators: ")
|
|
393
|
+
print(" - verilator")
|
|
394
|
+
print(" - questa")
|
|
395
|
+
return 1
|
|
396
|
+
|
|
397
|
+
if not args.no_compile:
|
|
398
|
+
rc = sim.compile()
|
|
399
|
+
if rc != 0:
|
|
400
|
+
return rc
|
|
401
|
+
return sim.run(args.inner_cmd[1:], gui=args.gui)
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
if __name__ == '__main__':
|
|
405
|
+
sys.exit(__main__(sys.argv))
|
esiaccel/bin/esiquery.exe
CHANGED
|
Binary file
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
//===- Cosim_DpiPkg.sv - ESI cosim DPI declarations ---------*- verilog -*-===//
|
|
2
|
+
//
|
|
3
|
+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
4
|
+
// See https://llvm.org/LICENSE.txt for license information.
|
|
5
|
+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
6
|
+
//
|
|
7
|
+
//===----------------------------------------------------------------------===//
|
|
8
|
+
//
|
|
9
|
+
// Package: Cosim_DpiPkg
|
|
10
|
+
//
|
|
11
|
+
// DPI-exposed funcs for cosimserver cosimulation unit-test.
|
|
12
|
+
//
|
|
13
|
+
//===----------------------------------------------------------------------===//
|
|
14
|
+
|
|
15
|
+
package Cosim_DpiPkg;
|
|
16
|
+
|
|
17
|
+
// --------------------- Cosim RPC Server --------------------------------------
|
|
18
|
+
|
|
19
|
+
// Start cosimserver (spawns server for HW-initiated work, listens for
|
|
20
|
+
// connections from new SW-clients).
|
|
21
|
+
import "DPI-C" sv2cCosimserverInit = function int cosim_init();
|
|
22
|
+
|
|
23
|
+
// Teardown cosimserver (disconnects from primary server port, stops connections
|
|
24
|
+
// from active clients).
|
|
25
|
+
import "DPI-C" sv2cCosimserverFinish = function void cosim_finish();
|
|
26
|
+
|
|
27
|
+
// --------------------- Endpoint Management -----------------------------------
|
|
28
|
+
|
|
29
|
+
// Register simulated device endpoints.
|
|
30
|
+
// - return 0 on success, non-zero on failure (duplicate EP registered).
|
|
31
|
+
import "DPI-C" sv2cCosimserverEpRegister =
|
|
32
|
+
function int cosim_ep_register(
|
|
33
|
+
// The endpoint ID.
|
|
34
|
+
input string endpoint_id,
|
|
35
|
+
// The ESI type id which the _RPC client_ is sending us.
|
|
36
|
+
input string from_host_type_id,
|
|
37
|
+
// The send types max size, in bytes.
|
|
38
|
+
input int from_host_type_size,
|
|
39
|
+
// The ESI type id which we are sending to the _RPC client_.
|
|
40
|
+
input string to_host_type_id,
|
|
41
|
+
// The recv types max size, in bytes.
|
|
42
|
+
input int to_host_type_size);
|
|
43
|
+
|
|
44
|
+
// --------------------- Endpoint Accessors ------------------------------------
|
|
45
|
+
|
|
46
|
+
// Attempt to send data to a client.
|
|
47
|
+
// - return 0 on success, negative on failure (unregistered EP).
|
|
48
|
+
import "DPI-C" sv2cCosimserverEpTryPut =
|
|
49
|
+
function int cosim_ep_tryput(
|
|
50
|
+
// The ID of the endpoint to which the data should be sent.
|
|
51
|
+
input string endpoint_id,
|
|
52
|
+
// A data buffer.
|
|
53
|
+
input byte unsigned data[],
|
|
54
|
+
// (Optional) Size of the buffer. If negative, will be dynamically detected.
|
|
55
|
+
input int data_size = -1
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
// Attempt to recieve data from a client.
|
|
59
|
+
// - Returns negative when call failed (e.g. EP not registered).
|
|
60
|
+
// - If no message, return 0 with size_bytes == 0.
|
|
61
|
+
// - Assumes buffer is large enough to contain entire message. Fails if not
|
|
62
|
+
// large enough. (In the future, will add support for getting the message into
|
|
63
|
+
// a fixed-size buffer over multiple calls.)
|
|
64
|
+
import "DPI-C" sv2cCosimserverEpTryGet =
|
|
65
|
+
function int cosim_ep_tryget(
|
|
66
|
+
// The ID of the endpoint from which data should be recieved.
|
|
67
|
+
input string endpoint_id,
|
|
68
|
+
// The buffer in which to put the data. This should be 'output', but the
|
|
69
|
+
// open source simulator Verilator doesn't seem to have a way to do this.
|
|
70
|
+
inout byte unsigned data[],
|
|
71
|
+
// Input: indicates the size of the data[] buffer. If -1, dynamically detect
|
|
72
|
+
// size.
|
|
73
|
+
// Output: the size of the message.
|
|
74
|
+
inout int unsigned data_size
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
// --------------------- Manifest ----------------------------------------------
|
|
78
|
+
|
|
79
|
+
import "DPI-C" sv2cCosimserverSetManifest =
|
|
80
|
+
function void cosim_set_manifest(
|
|
81
|
+
input int signed esi_version,
|
|
82
|
+
input byte unsigned compressed_manifest[]
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
endpackage // Cosim_DpiPkg
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
//===- Cosim_Endpoint.sv - ESI cosim primary RTL module -----*- verilog -*-===//
|
|
2
|
+
//
|
|
3
|
+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
4
|
+
// See https://llvm.org/LICENSE.txt for license information.
|
|
5
|
+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
6
|
+
//
|
|
7
|
+
//===----------------------------------------------------------------------===//
|
|
8
|
+
//
|
|
9
|
+
// Package: Cosim_DpiPkg
|
|
10
|
+
//
|
|
11
|
+
// Main cosim <--> dpi bridge module.
|
|
12
|
+
//
|
|
13
|
+
//===----------------------------------------------------------------------===//
|
|
14
|
+
|
|
15
|
+
import Cosim_DpiPkg::*;
|
|
16
|
+
|
|
17
|
+
module Cosim_Endpoint_ToHost
|
|
18
|
+
#(
|
|
19
|
+
parameter string ENDPOINT_ID = "",
|
|
20
|
+
parameter string TO_HOST_TYPE_ID = "",
|
|
21
|
+
parameter int TO_HOST_SIZE_BITS = -1
|
|
22
|
+
)
|
|
23
|
+
(
|
|
24
|
+
input logic clk,
|
|
25
|
+
input logic rst,
|
|
26
|
+
|
|
27
|
+
input logic DataInValid,
|
|
28
|
+
output logic DataInReady,
|
|
29
|
+
input logic [TO_HOST_SIZE_BITS-1:0] DataIn
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
initial begin
|
|
33
|
+
int rc;
|
|
34
|
+
rc = cosim_init();
|
|
35
|
+
if (rc != 0)
|
|
36
|
+
$error("Cosim init failed (%d)", rc);
|
|
37
|
+
rc = cosim_ep_register(ENDPOINT_ID, "", 0,
|
|
38
|
+
TO_HOST_TYPE_ID, TO_HOST_SIZE_BYTES);
|
|
39
|
+
if (rc != 0)
|
|
40
|
+
$error("Cosim endpoint (%s) register failed: %d", ENDPOINT_ID, rc);
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
/// **********************
|
|
44
|
+
/// Data in management.
|
|
45
|
+
///
|
|
46
|
+
|
|
47
|
+
localparam int TO_HOST_SIZE_BYTES = int'((TO_HOST_SIZE_BITS+7)/8);
|
|
48
|
+
// The number of bits over a byte.
|
|
49
|
+
localparam int TO_HOST_SIZE_BITS_DIFF = TO_HOST_SIZE_BITS % 8;
|
|
50
|
+
localparam int TO_HOST_SIZE_BYTES_FLOOR = int'(TO_HOST_SIZE_BITS/8);
|
|
51
|
+
localparam int TO_HOST_SIZE_BYTES_FLOOR_IN_BITS
|
|
52
|
+
= TO_HOST_SIZE_BYTES_FLOOR * 8;
|
|
53
|
+
|
|
54
|
+
assign DataInReady = 1'b1;
|
|
55
|
+
byte unsigned DataInBuffer[TO_HOST_SIZE_BYTES-1:0];
|
|
56
|
+
|
|
57
|
+
always@(posedge clk) begin
|
|
58
|
+
if (~rst) begin
|
|
59
|
+
if (DataInValid) begin
|
|
60
|
+
int rc;
|
|
61
|
+
rc = cosim_ep_tryput(ENDPOINT_ID, DataInBuffer, TO_HOST_SIZE_BYTES);
|
|
62
|
+
if (rc != 0)
|
|
63
|
+
$error("cosim_ep_tryput(%s, *, %d) = %d Error! (Data lost)",
|
|
64
|
+
ENDPOINT_ID, TO_HOST_SIZE_BYTES, rc);
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
// Assign packed input bit array to unpacked byte array.
|
|
70
|
+
genvar iIn;
|
|
71
|
+
generate
|
|
72
|
+
for (iIn=0; iIn<TO_HOST_SIZE_BYTES_FLOOR; iIn++)
|
|
73
|
+
assign DataInBuffer[iIn] = DataIn[((iIn+1)*8)-1:iIn*8];
|
|
74
|
+
if (TO_HOST_SIZE_BITS_DIFF != 0)
|
|
75
|
+
// If the type is not a multiple of 8, we've got to copy the extra bits.
|
|
76
|
+
assign DataInBuffer[TO_HOST_SIZE_BYTES - 1]
|
|
77
|
+
[TO_HOST_SIZE_BITS_DIFF - 1:0] =
|
|
78
|
+
DataIn[(TO_HOST_SIZE_BYTES_FLOOR_IN_BITS +
|
|
79
|
+
TO_HOST_SIZE_BITS_DIFF - 1) :
|
|
80
|
+
TO_HOST_SIZE_BYTES_FLOOR_IN_BITS];
|
|
81
|
+
endgenerate
|
|
82
|
+
|
|
83
|
+
initial begin
|
|
84
|
+
$display("TO_HOST_SIZE_BITS: %d", TO_HOST_SIZE_BITS);
|
|
85
|
+
$display("TO_HOST_SIZE_BYTES: %d", TO_HOST_SIZE_BYTES);
|
|
86
|
+
$display("TO_HOST_SIZE_BITS_DIFF: %d", TO_HOST_SIZE_BITS_DIFF);
|
|
87
|
+
$display("TO_HOST_SIZE_BYTES_FLOOR: %d", TO_HOST_SIZE_BYTES_FLOOR);
|
|
88
|
+
$display("TO_HOST_SIZE_BYTES_FLOOR_IN_BITS: %d",
|
|
89
|
+
TO_HOST_SIZE_BYTES_FLOOR_IN_BITS);
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
endmodule
|
|
93
|
+
|
|
94
|
+
module Cosim_Endpoint_FromHost
|
|
95
|
+
#(
|
|
96
|
+
parameter string ENDPOINT_ID = "",
|
|
97
|
+
parameter string FROM_HOST_TYPE_ID = "",
|
|
98
|
+
parameter int FROM_HOST_SIZE_BITS = -1
|
|
99
|
+
)
|
|
100
|
+
(
|
|
101
|
+
input logic clk,
|
|
102
|
+
input logic rst,
|
|
103
|
+
|
|
104
|
+
output logic DataOutValid,
|
|
105
|
+
input logic DataOutReady,
|
|
106
|
+
output logic [FROM_HOST_SIZE_BITS-1:0] DataOut
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
// Handle initialization logic.
|
|
110
|
+
initial begin
|
|
111
|
+
int rc;
|
|
112
|
+
rc = cosim_init();
|
|
113
|
+
if (rc != 0)
|
|
114
|
+
$error("Cosim init failed (%d)", rc);
|
|
115
|
+
rc = cosim_ep_register(ENDPOINT_ID, FROM_HOST_TYPE_ID, FROM_HOST_SIZE_BYTES,
|
|
116
|
+
"", 0);
|
|
117
|
+
if (rc != 0)
|
|
118
|
+
$error("Cosim endpoint (%s) register failed: %d", ENDPOINT_ID, rc);
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
/// *******************
|
|
122
|
+
/// Data out management.
|
|
123
|
+
///
|
|
124
|
+
|
|
125
|
+
localparam int FROM_HOST_SIZE_BYTES = int'((FROM_HOST_SIZE_BITS+7)/8);
|
|
126
|
+
// The number of bits over a byte.
|
|
127
|
+
localparam int FROM_HOST_SIZE_BITS_DIFF = FROM_HOST_SIZE_BITS % 8;
|
|
128
|
+
localparam int FROM_HOST_SIZE_BYTES_FLOOR = int'(FROM_HOST_SIZE_BITS/8);
|
|
129
|
+
localparam int FROM_HOST_SIZE_BYTES_FLOOR_IN_BITS
|
|
130
|
+
= FROM_HOST_SIZE_BYTES_FLOOR * 8;
|
|
131
|
+
|
|
132
|
+
byte unsigned DataOutBuffer[FROM_HOST_SIZE_BYTES-1:0];
|
|
133
|
+
always @(posedge clk) begin
|
|
134
|
+
if (~rst) begin
|
|
135
|
+
if (DataOutValid && DataOutReady) // A transfer occurred.
|
|
136
|
+
DataOutValid <= 1'b0;
|
|
137
|
+
|
|
138
|
+
if (!DataOutValid || DataOutReady) begin
|
|
139
|
+
int data_limit;
|
|
140
|
+
int rc;
|
|
141
|
+
|
|
142
|
+
data_limit = FROM_HOST_SIZE_BYTES;
|
|
143
|
+
rc = cosim_ep_tryget(ENDPOINT_ID, DataOutBuffer, data_limit);
|
|
144
|
+
if (rc < 0) begin
|
|
145
|
+
$error("cosim_ep_tryget(%s, *, %d -> %d) returned an error (%d)",
|
|
146
|
+
ENDPOINT_ID, FROM_HOST_SIZE_BYTES, data_limit, rc);
|
|
147
|
+
end else if (rc > 0) begin
|
|
148
|
+
$error("cosim_ep_tryget(%s, *, %d -> %d) had data left over! (%d)",
|
|
149
|
+
ENDPOINT_ID, FROM_HOST_SIZE_BYTES, data_limit, rc);
|
|
150
|
+
end else if (rc == 0) begin
|
|
151
|
+
if (data_limit == FROM_HOST_SIZE_BYTES)
|
|
152
|
+
DataOutValid <= 1'b1;
|
|
153
|
+
else if (data_limit == 0)
|
|
154
|
+
begin end // No message.
|
|
155
|
+
else
|
|
156
|
+
$error(
|
|
157
|
+
"cosim_ep_tryget(%s, *, %d -> %d) did not load entire buffer!",
|
|
158
|
+
ENDPOINT_ID, FROM_HOST_SIZE_BYTES, data_limit);
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end else begin
|
|
162
|
+
DataOutValid <= 1'b0;
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
// Assign packed output bit array from unpacked byte array.
|
|
167
|
+
genvar iOut;
|
|
168
|
+
generate
|
|
169
|
+
for (iOut=0; iOut<FROM_HOST_SIZE_BYTES_FLOOR; iOut++)
|
|
170
|
+
assign DataOut[((iOut+1)*8)-1:iOut*8] = DataOutBuffer[iOut];
|
|
171
|
+
if (FROM_HOST_SIZE_BITS_DIFF != 0)
|
|
172
|
+
// If the type is not a multiple of 8, we've got to copy the extra bits.
|
|
173
|
+
assign DataOut[(FROM_HOST_SIZE_BYTES_FLOOR_IN_BITS +
|
|
174
|
+
FROM_HOST_SIZE_BITS_DIFF - 1) :
|
|
175
|
+
FROM_HOST_SIZE_BYTES_FLOOR_IN_BITS]
|
|
176
|
+
= DataOutBuffer[FROM_HOST_SIZE_BYTES - 1]
|
|
177
|
+
[FROM_HOST_SIZE_BITS_DIFF - 1 : 0];
|
|
178
|
+
endgenerate
|
|
179
|
+
|
|
180
|
+
initial begin
|
|
181
|
+
$display("FROM_HOST_SIZE_BITS: %d", FROM_HOST_SIZE_BITS);
|
|
182
|
+
$display("FROM_HOST_SIZE_BYTES: %d", FROM_HOST_SIZE_BYTES);
|
|
183
|
+
$display("FROM_HOST_SIZE_BITS_DIFF: %d", FROM_HOST_SIZE_BITS_DIFF);
|
|
184
|
+
$display("FROM_HOST_SIZE_BYTES_FLOOR: %d", FROM_HOST_SIZE_BYTES_FLOOR);
|
|
185
|
+
$display("FROM_HOST_SIZE_BYTES_FLOOR_IN_BITS: %d",
|
|
186
|
+
FROM_HOST_SIZE_BYTES_FLOOR_IN_BITS);
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
endmodule
|