esiaccel 0.1.4.dev31__cp310-cp310-win_amd64.whl → 0.2.3.dev80__cp310-cp310-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.
Files changed (58) hide show
  1. esiaccel/CosimBackend.dll +0 -0
  2. esiaccel/CosimBackend.lib +0 -0
  3. esiaccel/CosimRpc.dll +0 -0
  4. esiaccel/CosimRpc.lib +0 -0
  5. esiaccel/ESICppRuntime.dll +0 -0
  6. esiaccel/ESICppRuntime.lib +0 -0
  7. esiaccel/EsiCosimDpiServer.dll +0 -0
  8. esiaccel/EsiCosimDpiServer.lib +0 -0
  9. esiaccel/{lib/MtiPli.dll → MtiPli.dll} +0 -0
  10. esiaccel/{lib/MtiPli.lib → MtiPli.lib} +0 -0
  11. esiaccel/__init__.py +22 -4
  12. esiaccel/abseil_dll.dll +0 -0
  13. esiaccel/accelerator.py +37 -5
  14. esiaccel/cares.dll +0 -0
  15. esiaccel/cmake/esiaccelConfig.cmake +34 -0
  16. esiaccel/codegen.py +3 -3
  17. esiaccel/cosim/Cosim_CycleCount.sv +84 -0
  18. esiaccel/cosim/Cosim_Endpoint.sv +61 -32
  19. esiaccel/cosim/driver.cpp +6 -6
  20. esiaccel/cosim/driver.sv +14 -0
  21. esiaccel/cosim/questa.py +141 -0
  22. esiaccel/cosim/simulator.py +383 -0
  23. esiaccel/cosim/verilator.py +92 -0
  24. esiaccel/esi-cosim.py +104 -0
  25. esiaccel/esiCppAccel.cp312-win_amd64.pyd +0 -0
  26. esiaccel/esiquery.exe +0 -0
  27. esiaccel/include/esi/Accelerator.h +14 -17
  28. esiaccel/include/esi/CLI.h +5 -5
  29. esiaccel/include/esi/Common.h +19 -2
  30. esiaccel/include/esi/Context.h +17 -9
  31. esiaccel/include/esi/Design.h +9 -4
  32. esiaccel/include/esi/Manifest.h +0 -2
  33. esiaccel/include/esi/Ports.h +230 -23
  34. esiaccel/include/esi/Services.h +92 -31
  35. esiaccel/include/esi/Types.h +162 -10
  36. esiaccel/include/esi/Values.h +313 -0
  37. esiaccel/include/esi/backends/Cosim.h +5 -12
  38. esiaccel/include/esi/backends/RpcClient.h +97 -0
  39. esiaccel/include/esi/backends/RpcServer.h +21 -3
  40. esiaccel/libcrypto-3-x64.dll +0 -0
  41. esiaccel/libprotobuf.dll +0 -0
  42. esiaccel/libssl-3-x64.dll +0 -0
  43. esiaccel/re2.dll +0 -0
  44. esiaccel/types.py +66 -26
  45. esiaccel/utils.py +21 -3
  46. esiaccel/zlib1.dll +0 -0
  47. {esiaccel-0.1.4.dev31.dist-info → esiaccel-0.2.3.dev80.dist-info}/METADATA +1 -1
  48. esiaccel-0.2.3.dev80.dist-info/RECORD +58 -0
  49. esiaccel/bin/esi-cosim.py +0 -423
  50. esiaccel/bin/esiquery.exe +0 -0
  51. esiaccel/esiCppAccel.cp310-win_amd64.pyd +0 -0
  52. esiaccel/lib/EsiCosimDpiServer.dll +0 -0
  53. esiaccel/lib/EsiCosimDpiServer.lib +0 -0
  54. esiaccel-0.1.4.dev31.dist-info/RECORD +0 -43
  55. {esiaccel-0.1.4.dev31.dist-info → esiaccel-0.2.3.dev80.dist-info}/WHEEL +0 -0
  56. {esiaccel-0.1.4.dev31.dist-info → esiaccel-0.2.3.dev80.dist-info}/entry_points.txt +0 -0
  57. {esiaccel-0.1.4.dev31.dist-info → esiaccel-0.2.3.dev80.dist-info}/licenses/LICENSE +0 -0
  58. {esiaccel-0.1.4.dev31.dist-info → esiaccel-0.2.3.dev80.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,383 @@
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
+
5
+ import os
6
+ import re
7
+ import signal
8
+ import socket
9
+ import subprocess
10
+ import time
11
+ from pathlib import Path
12
+ from typing import Dict, List, Optional, Callable, IO
13
+ import threading
14
+
15
+ _thisdir = Path(__file__).parent
16
+ CosimCollateralDir = _thisdir
17
+
18
+
19
+ def is_port_open(port) -> bool:
20
+ """Check if a TCP port is open locally."""
21
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
22
+ result = sock.connect_ex(('127.0.0.1', port))
23
+ sock.close()
24
+ return True if result == 0 else False
25
+
26
+
27
+ class SourceFiles:
28
+
29
+ def __init__(self, top: str) -> None:
30
+ # User source files.
31
+ self.user: List[Path] = []
32
+ # DPI shared objects.
33
+ self.dpi_so: List[str] = ["EsiCosimDpiServer"]
34
+ # DPI SV files.
35
+ self.dpi_sv: List[Path] = [
36
+ CosimCollateralDir / "Cosim_DpiPkg.sv",
37
+ CosimCollateralDir / "Cosim_Endpoint.sv",
38
+ CosimCollateralDir / "Cosim_CycleCount.sv",
39
+ CosimCollateralDir / "Cosim_Manifest.sv",
40
+ ]
41
+ # Name of the top module.
42
+ self.top = top
43
+
44
+ def add_file(self, file: Path):
45
+ """Add a single RTL file to the source list."""
46
+ if file.is_file():
47
+ self.user.append(file)
48
+ else:
49
+ raise FileNotFoundError(f"File {file} does not exist")
50
+
51
+ def add_dir(self, dir: Path):
52
+ """Add all the RTL files in a directory to the source list."""
53
+ for file in sorted(dir.iterdir()):
54
+ if file.is_file() and (file.suffix == ".sv" or file.suffix == ".v"):
55
+ self.user.append(file)
56
+ elif file.is_dir():
57
+ self.add_dir(file)
58
+
59
+ def dpi_so_paths(self) -> List[Path]:
60
+ """Return a list of all the DPI shared object files."""
61
+
62
+ def find_so(name: str) -> Path:
63
+ for path in Simulator.get_env().get("LD_LIBRARY_PATH", "").split(":"):
64
+ if os.name == "nt":
65
+ so = Path(path) / f"{name}.dll"
66
+ else:
67
+ so = Path(path) / f"lib{name}.so"
68
+ if so.exists():
69
+ return so
70
+ raise FileNotFoundError(f"Could not find {name}.so in LD_LIBRARY_PATH")
71
+
72
+ return [find_so(name) for name in self.dpi_so]
73
+
74
+ @property
75
+ def rtl_sources(self) -> List[Path]:
76
+ """Return a list of all the RTL source files."""
77
+ return self.dpi_sv + self.user
78
+
79
+
80
+ class SimProcess:
81
+
82
+ def __init__(self,
83
+ proc: subprocess.Popen,
84
+ port: int,
85
+ threads: Optional[List[threading.Thread]] = None,
86
+ gui: bool = False):
87
+ self.proc = proc
88
+ self.port = port
89
+ self.threads: List[threading.Thread] = threads or []
90
+ self.gui = gui
91
+
92
+ def force_stop(self):
93
+ """Make sure to stop the simulation no matter what."""
94
+ if self.proc:
95
+ os.killpg(os.getpgid(self.proc.pid), signal.SIGINT)
96
+ # Allow the simulation time to flush its outputs.
97
+ try:
98
+ self.proc.wait(timeout=1.0)
99
+ except subprocess.TimeoutExpired:
100
+ # If the simulation doesn't exit of its own free will, kill it.
101
+ self.proc.kill()
102
+
103
+ # Join reader threads (they should exit once pipes are closed).
104
+ for t in self.threads:
105
+ t.join()
106
+
107
+
108
+ class Simulator:
109
+
110
+ # Some RTL simulators don't use stderr for error messages. Everything goes to
111
+ # stdout. Boo! They should feel bad about this. Also, they can specify that
112
+ # broken behavior by overriding this.
113
+ UsesStderr = True
114
+
115
+ def __init__(self,
116
+ sources: SourceFiles,
117
+ run_dir: Path,
118
+ debug: bool,
119
+ run_stdout_callback: Optional[Callable[[str], None]] = None,
120
+ run_stderr_callback: Optional[Callable[[str], None]] = None,
121
+ compile_stdout_callback: Optional[Callable[[str], None]] = None,
122
+ compile_stderr_callback: Optional[Callable[[str], None]] = None,
123
+ make_default_logs: bool = True,
124
+ macro_definitions: Optional[Dict[str, str]] = None):
125
+ """Simulator base class.
126
+
127
+ Optional sinks can be provided for capturing output. If not provided,
128
+ the simulator will write to log files in `run_dir`.
129
+
130
+ Args:
131
+ sources: SourceFiles describing RTL/DPI inputs.
132
+ run_dir: Directory where build/run artifacts are placed.
133
+ debug: Enable cosim debug mode.
134
+ run_stdout_callback: Line-based callback for runtime stdout.
135
+ run_stderr_callback: Line-based callback for runtime stderr.
136
+ compile_stdout_callback: Line-based callback for compile stdout.
137
+ compile_stderr_callback: Line-based callback for compile stderr.
138
+ make_default_logs: If True and corresponding callback is not supplied,
139
+ create log file and emit via internally-created callback.
140
+ macro_definitions: Optional dictionary of macro definitions to be defined
141
+ during compilation.
142
+ """
143
+ self.sources = sources
144
+ self.run_dir = run_dir
145
+ self.debug = debug
146
+ self.macro_definitions = macro_definitions
147
+
148
+ # Unified list of any log file handles we opened.
149
+ self._default_files: List[IO[str]] = []
150
+
151
+ def _ensure_default(cb: Optional[Callable[[str], None]], filename: str):
152
+ """Return (callback, file_handle_or_None) with optional file creation.
153
+
154
+ Behavior:
155
+ * If a callback is provided, return it unchanged with no file.
156
+ * If no callback and make_default_logs is False, return (None, None).
157
+ * If no callback and make_default_logs is True, create a log file and
158
+ return a writer callback plus the opened file handle.
159
+ """
160
+ if cb is not None:
161
+ return cb, None
162
+ if not make_default_logs:
163
+ return None, None
164
+ p = self.run_dir / filename
165
+ p.parent.mkdir(parents=True, exist_ok=True)
166
+ logf = p.open("w+")
167
+ self._default_files.append(logf)
168
+
169
+ def _writer(line: str, _lf=logf):
170
+ _lf.write(line + "\n")
171
+ _lf.flush()
172
+
173
+ return _writer, logf
174
+
175
+ # Initialize all four (compile/run stdout/stderr) uniformly.
176
+ self._compile_stdout_cb, self._compile_stdout_log = _ensure_default(
177
+ compile_stdout_callback, 'compile_stdout.log')
178
+ self._compile_stderr_cb, self._compile_stderr_log = _ensure_default(
179
+ compile_stderr_callback, 'compile_stderr.log')
180
+ self._run_stdout_cb, self._run_stdout_log = _ensure_default(
181
+ run_stdout_callback, 'sim_stdout.log')
182
+ self._run_stderr_cb, self._run_stderr_log = _ensure_default(
183
+ run_stderr_callback, 'sim_stderr.log')
184
+
185
+ @staticmethod
186
+ def get_env() -> Dict[str, str]:
187
+ """Get the environment variables to locate shared objects."""
188
+
189
+ env = os.environ.copy()
190
+ env["LIBRARY_PATH"] = env.get("LIBRARY_PATH", "") + ":" + str(
191
+ _thisdir.parent / "lib")
192
+ env["LD_LIBRARY_PATH"] = env.get("LD_LIBRARY_PATH", "") + ":" + str(
193
+ _thisdir.parent / "lib")
194
+ return env
195
+
196
+ def compile_commands(self) -> List[List[str]]:
197
+ """Compile the sources. Returns the exit code of the simulation compiler."""
198
+ assert False, "Must be implemented by subclass"
199
+
200
+ def compile(self) -> int:
201
+ cmds = self.compile_commands()
202
+ self.run_dir.mkdir(parents=True, exist_ok=True)
203
+ for cmd in cmds:
204
+ ret = self._start_process_with_callbacks(
205
+ cmd,
206
+ env=Simulator.get_env(),
207
+ cwd=None,
208
+ stdout_cb=self._compile_stdout_cb,
209
+ stderr_cb=self._compile_stderr_cb,
210
+ wait=True)
211
+ if isinstance(ret, int) and ret != 0:
212
+ print("====== Compilation failure")
213
+
214
+ # If we have the default file loggers, print the compilation logs to
215
+ # console. Else, assume that the user has already captured them.
216
+ if self.UsesStderr:
217
+ if self._compile_stderr_log is not None:
218
+ self._compile_stderr_log.seek(0)
219
+ print(self._compile_stderr_log.read())
220
+ else:
221
+ if self._compile_stdout_log is not None:
222
+ self._compile_stdout_log.seek(0)
223
+ print(self._compile_stdout_log.read())
224
+
225
+ return ret
226
+ return 0
227
+
228
+ def run_command(self, gui: bool) -> List[str]:
229
+ """Return the command to run the simulation."""
230
+ assert False, "Must be implemented by subclass"
231
+
232
+ def run_proc(self, gui: bool = False) -> SimProcess:
233
+ """Run the simulation process. Returns the Popen object and the port which
234
+ the simulation is listening on.
235
+
236
+ If user-provided stdout/stderr sinks were supplied in the constructor,
237
+ they are used. Otherwise, log files are created in `run_dir`.
238
+ """
239
+ self.run_dir.mkdir(parents=True, exist_ok=True)
240
+
241
+ env_gui = os.environ.get("COSIM_GUI", "0")
242
+ if env_gui != "0":
243
+ gui = True
244
+
245
+ # Erase the config file if it exists. We don't want to read
246
+ # an old config.
247
+ portFileName = self.run_dir / "cosim.cfg"
248
+ if os.path.exists(portFileName):
249
+ os.remove(portFileName)
250
+
251
+ # Run the simulation.
252
+ simEnv = Simulator.get_env()
253
+ if self.debug:
254
+ simEnv["COSIM_DEBUG_FILE"] = "cosim_debug.log"
255
+ if "DEBUG_PERIOD" not in simEnv:
256
+ # Slow the simulation down to one tick per millisecond.
257
+ simEnv["DEBUG_PERIOD"] = "1"
258
+ rcmd = self.run_command(gui)
259
+ # Start process with asynchronous output capture.
260
+ proc, threads = self._start_process_with_callbacks(
261
+ rcmd,
262
+ env=simEnv,
263
+ cwd=self.run_dir,
264
+ stdout_cb=self._run_stdout_cb,
265
+ stderr_cb=self._run_stderr_cb,
266
+ wait=False)
267
+
268
+ # Get the port which the simulation RPC selected.
269
+ checkCount = 0
270
+ while (not os.path.exists(portFileName)) and \
271
+ proc.poll() is None:
272
+ time.sleep(0.1)
273
+ checkCount += 1
274
+ if checkCount > 500 and not gui:
275
+ raise Exception(f"Cosim never wrote cfg file: {portFileName}")
276
+ port = -1
277
+ while port < 0:
278
+ portFile = open(portFileName, "r")
279
+ for line in portFile.readlines():
280
+ m = re.match("port: (\\d+)", line)
281
+ if m is not None:
282
+ port = int(m.group(1))
283
+ portFile.close()
284
+
285
+ # Wait for the simulation to start accepting RPC connections.
286
+ checkCount = 0
287
+ while not is_port_open(port):
288
+ checkCount += 1
289
+ if checkCount > 200:
290
+ raise Exception(f"Cosim RPC port ({port}) never opened")
291
+ if proc.poll() is not None:
292
+ raise Exception("Simulation exited early")
293
+ time.sleep(0.05)
294
+ return SimProcess(proc=proc, port=port, threads=threads, gui=gui)
295
+
296
+ def _start_process_with_callbacks(
297
+ self, cmd: List[str], env: Optional[Dict[str, str]], cwd: Optional[Path],
298
+ stdout_cb: Optional[Callable[[str],
299
+ None]], stderr_cb: Optional[Callable[[str],
300
+ None]],
301
+ wait: bool) -> int | tuple[subprocess.Popen, List[threading.Thread]]:
302
+ """Start a subprocess and stream its stdout/stderr to callbacks.
303
+
304
+ If wait is True, blocks until process completes and returns its exit code.
305
+ If wait is False, returns the Popen object (threads keep streaming).
306
+ """
307
+ if os.name == "posix":
308
+ proc = subprocess.Popen(cmd,
309
+ stdout=subprocess.PIPE,
310
+ stderr=subprocess.PIPE,
311
+ env=env,
312
+ cwd=cwd,
313
+ text=True,
314
+ preexec_fn=os.setsid)
315
+ else: # windows
316
+ proc = subprocess.Popen(cmd,
317
+ stdout=subprocess.PIPE,
318
+ stderr=subprocess.PIPE,
319
+ env=env,
320
+ cwd=cwd,
321
+ text=True,
322
+ creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
323
+
324
+ def _reader(pipe, cb):
325
+ if pipe is None:
326
+ return
327
+ for raw in pipe:
328
+ if raw.endswith('\n'):
329
+ raw = raw[:-1]
330
+ if cb:
331
+ try:
332
+ cb(raw)
333
+ except Exception as e:
334
+ print(f"Exception in simulator output callback: {e}")
335
+
336
+ threads: List[threading.Thread] = [
337
+ threading.Thread(target=_reader,
338
+ args=(proc.stdout, stdout_cb),
339
+ daemon=True),
340
+ threading.Thread(target=_reader,
341
+ args=(proc.stderr, stderr_cb),
342
+ daemon=True),
343
+ ]
344
+ for t in threads:
345
+ t.start()
346
+ if wait:
347
+ for t in threads:
348
+ t.join()
349
+ return proc.wait()
350
+ return proc, threads
351
+
352
+ def run(self,
353
+ inner_command: str,
354
+ gui: bool = False,
355
+ server_only: bool = False) -> int:
356
+ """Start the simulation then run the command specified. Kill the simulation
357
+ when the command exits."""
358
+
359
+ # 'simProc' is accessed in the finally block. Declare it here to avoid
360
+ # syntax errors in that block.
361
+ simProc = None
362
+ try:
363
+ simProc = self.run_proc(gui=gui)
364
+ if server_only:
365
+ # wait for user input to kill the server
366
+ input(
367
+ f"Running in server-only mode on port {simProc.port} - Press anything to kill the server..."
368
+ )
369
+ return 0
370
+ else:
371
+ # Run the inner command, passing the connection info via environment vars.
372
+ testEnv = os.environ.copy()
373
+ testEnv["ESI_COSIM_PORT"] = str(simProc.port)
374
+ testEnv["ESI_COSIM_HOST"] = "localhost"
375
+ ret = subprocess.run(inner_command, cwd=os.getcwd(),
376
+ env=testEnv).returncode
377
+ if simProc.gui:
378
+ print("GUI mode - waiting for simulator to exit...")
379
+ simProc.proc.wait()
380
+ return ret
381
+ finally:
382
+ if simProc and simProc.proc.poll() is None:
383
+ simProc.force_stop()
@@ -0,0 +1,92 @@
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
+
5
+ import os
6
+ from pathlib import Path
7
+ from typing import List, Optional, Callable, Dict
8
+
9
+ from .simulator import CosimCollateralDir, Simulator, SourceFiles
10
+
11
+
12
+ class Verilator(Simulator):
13
+ """Run and compile funcs for Verilator."""
14
+
15
+ DefaultDriver = CosimCollateralDir / "driver.cpp"
16
+
17
+ def __init__(
18
+ self,
19
+ sources: SourceFiles,
20
+ run_dir: Path,
21
+ debug: bool,
22
+ run_stdout_callback: Optional[Callable[[str], None]] = None,
23
+ run_stderr_callback: Optional[Callable[[str], None]] = None,
24
+ compile_stdout_callback: Optional[Callable[[str], None]] = None,
25
+ compile_stderr_callback: Optional[Callable[[str], None]] = None,
26
+ make_default_logs: bool = True,
27
+ macro_definitions: Optional[Dict[str, str]] = None,
28
+ ):
29
+ super().__init__(
30
+ sources=sources,
31
+ run_dir=run_dir,
32
+ debug=debug,
33
+ run_stdout_callback=run_stdout_callback,
34
+ run_stderr_callback=run_stderr_callback,
35
+ compile_stdout_callback=compile_stdout_callback,
36
+ compile_stderr_callback=compile_stderr_callback,
37
+ make_default_logs=make_default_logs,
38
+ macro_definitions=macro_definitions,
39
+ )
40
+ self.verilator = "verilator"
41
+ if "VERILATOR_PATH" in os.environ:
42
+ self.verilator = os.environ["VERILATOR_PATH"]
43
+
44
+ def compile_commands(self) -> List[List[str]]:
45
+ cmd: List[str] = [
46
+ self.verilator,
47
+ "--cc",
48
+ ]
49
+
50
+ if self.macro_definitions:
51
+ cmd += [
52
+ f"+define+{k}={v}" if v is not None else f"+define+{k}"
53
+ for k, v in self.macro_definitions.items()
54
+ ]
55
+
56
+ cmd += [
57
+ "--top-module",
58
+ self.sources.top,
59
+ "-DSIMULATION",
60
+ "-Wno-TIMESCALEMOD",
61
+ "-Wno-fatal",
62
+ "-sv",
63
+ "--exe",
64
+ "--build",
65
+ "-j",
66
+ "0",
67
+ "--output-split",
68
+ "--autoflush",
69
+ "--assert",
70
+ str(Verilator.DefaultDriver),
71
+ ]
72
+ cflags = [
73
+ "-DTOP_MODULE=" + self.sources.top,
74
+ ]
75
+ if self.debug:
76
+ cmd += [
77
+ "--trace-fst", "--trace-params", "--trace-structs",
78
+ "--trace-underscore"
79
+ ]
80
+ cflags.append("-DTRACE")
81
+ if len(cflags) > 0:
82
+ cmd += ["-CFLAGS", " ".join(cflags)]
83
+ if len(self.sources.dpi_so) > 0:
84
+ cmd += ["-LDFLAGS", " ".join(["-l" + so for so in self.sources.dpi_so])]
85
+ cmd += [str(p) for p in self.sources.rtl_sources]
86
+ return [cmd]
87
+
88
+ def run_command(self, gui: bool):
89
+ if gui:
90
+ raise RuntimeError("Verilator does not support GUI mode.")
91
+ exe = Path.cwd() / "obj_dir" / ("V" + self.sources.top)
92
+ return [str(exe)]
esiaccel/esi-cosim.py ADDED
@@ -0,0 +1,104 @@
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
+ from pathlib import Path
18
+ import sys
19
+ import textwrap
20
+ from typing import Dict, List
21
+
22
+ from esiaccel.cosim.questa import Questa
23
+ from esiaccel.cosim.verilator import Verilator
24
+ from esiaccel.cosim.simulator import SourceFiles
25
+
26
+
27
+ def __main__(args):
28
+ argparser = argparse.ArgumentParser(
29
+ description="Wrap a 'inner_cmd' in an ESI cosimulation environment.",
30
+ formatter_class=argparse.RawDescriptionHelpFormatter,
31
+ epilog=textwrap.dedent("""
32
+ Notes:
33
+ - For Verilator, libEsiCosimDpiServer.so must be in the dynamic
34
+ library runtime search path (LD_LIBRARY_PATH) and link time path
35
+ (LIBRARY_PATH). If it is installed to a standard location (e.g.
36
+ /usr/lib), this should be handled automatically.
37
+ - This script needs to sit in the same directory as the ESI support
38
+ SystemVerilog (e.g. Cosim_DpiPkg.sv, Cosim_MMIO.sv, etc.). It can,
39
+ however, be soft linked to a different location.
40
+ - The simulator executable(s) must be in your PATH.
41
+ """))
42
+
43
+ argparser.add_argument(
44
+ "--sim",
45
+ type=str,
46
+ default="verilator",
47
+ help="Name of the RTL simulator to use or path to an executable.")
48
+ argparser.add_argument("--rundir",
49
+ default="run",
50
+ help="Directory in which simulation should be run.")
51
+ argparser.add_argument(
52
+ "--top",
53
+ default="ESI_Cosim_Top",
54
+ help="Name of the 'top' module to use in the simulation.")
55
+ argparser.add_argument("--no-compile",
56
+ action="store_true",
57
+ help="Do not run the compile.")
58
+ argparser.add_argument("--debug",
59
+ action="store_true",
60
+ help="Enable debug output.")
61
+ argparser.add_argument("--gui",
62
+ action="store_true",
63
+ help="Run the simulator in GUI mode (if supported).")
64
+ argparser.add_argument("--source",
65
+ help="Directories containing the source files.",
66
+ default="hw")
67
+
68
+ argparser.add_argument("inner_cmd",
69
+ nargs=argparse.REMAINDER,
70
+ help="Command to run in the simulation environment.")
71
+
72
+ argparser.add_argument(
73
+ "--server-only",
74
+ action="store_true",
75
+ help="Only run the cosim server, and do not run any inner command.")
76
+
77
+ if len(args) <= 1:
78
+ argparser.print_help()
79
+ return
80
+ args = argparser.parse_args(args[1:])
81
+
82
+ sources = SourceFiles(args.top)
83
+ sources.add_dir(Path(args.source))
84
+
85
+ if args.sim == "verilator":
86
+ sim = Verilator(sources, Path(args.rundir), args.debug)
87
+ elif args.sim == "questa":
88
+ sim = Questa(sources, Path(args.rundir), args.debug)
89
+ else:
90
+ print("Unknown simulator: " + args.sim)
91
+ print("Supported simulators: ")
92
+ print(" - verilator")
93
+ print(" - questa")
94
+ return 1
95
+
96
+ if not args.no_compile:
97
+ rc = sim.compile()
98
+ if rc != 0:
99
+ return rc
100
+ return sim.run(args.inner_cmd[1:], gui=args.gui, server_only=args.server_only)
101
+
102
+
103
+ if __name__ == '__main__':
104
+ sys.exit(__main__(sys.argv))
Binary file
esiaccel/esiquery.exe ADDED
Binary file
@@ -39,14 +39,24 @@ namespace esi {
39
39
  class AcceleratorServiceThread;
40
40
 
41
41
  //===----------------------------------------------------------------------===//
42
- // Constants used by low-level APIs.
42
+ // Metadata constants which may or may not be used by various backends. Provided
43
+ // here since they are intended to be somewhat standard.
43
44
  //===----------------------------------------------------------------------===//
44
45
 
45
46
  constexpr uint32_t MetadataOffset = 8;
47
+
46
48
  constexpr uint64_t MagicNumberLo = 0xE5100E51;
47
49
  constexpr uint64_t MagicNumberHi = 0x207D98E5;
48
50
  constexpr uint64_t MagicNumber = MagicNumberLo | (MagicNumberHi << 32);
51
+ constexpr uint64_t MagicNumberOffset = 0;
52
+
49
53
  constexpr uint32_t ExpectedVersionNumber = 0;
54
+ constexpr uint64_t VersionNumberOffset = 8;
55
+
56
+ constexpr uint32_t ManifestPtrOffset = 0x10;
57
+
58
+ constexpr uint32_t CycleCountOffset = 0x20;
59
+ constexpr uint32_t CoreFreqOffset = 0x28;
50
60
 
51
61
  //===----------------------------------------------------------------------===//
52
62
  // Accelerator design hierarchy root.
@@ -65,8 +75,8 @@ public:
65
75
  Accelerator(std::optional<ModuleInfo> info,
66
76
  std::vector<std::unique_ptr<Instance>> children,
67
77
  std::vector<services::Service *> services,
68
- std::vector<std::unique_ptr<BundlePort>> &ports)
69
- : HWModule(info, std::move(children), services, ports) {}
78
+ std::vector<std::unique_ptr<BundlePort>> &&ports)
79
+ : HWModule(info, std::move(children), services, std::move(ports)) {}
70
80
  };
71
81
 
72
82
  //===----------------------------------------------------------------------===//
@@ -86,13 +96,6 @@ public:
86
96
  /// Disconnect from the accelerator cleanly.
87
97
  virtual void disconnect();
88
98
 
89
- // While building the design, keep around a std::map of active services
90
- // indexed by the service name. When a new service is encountered during
91
- // descent, add it to the table (perhaps overwriting one). Modifications to
92
- // the table only apply to the current branch, so copy this and update it at
93
- // each level of the tree.
94
- using ServiceTable = std::map<std::string, services::Service *>;
95
-
96
99
  /// Return a pointer to the accelerator 'service' thread (or threads). If the
97
100
  /// thread(s) are not running, they will be started when this method is
98
101
  /// called. `std::thread` is used. If users don't want the runtime to spin up
@@ -165,7 +168,7 @@ private:
165
168
 
166
169
  /// Cache services via a unique_ptr so they get free'd automatically when
167
170
  /// Accelerator objects get deconstructed.
168
- using ServiceCacheKey = std::tuple<const std::type_info *, AppIDPath>;
171
+ using ServiceCacheKey = std::tuple<std::string, AppIDPath>;
169
172
  std::map<ServiceCacheKey, std::unique_ptr<Service>> serviceCache;
170
173
 
171
174
  std::unique_ptr<AcceleratorServiceThread> serviceThread;
@@ -176,12 +179,6 @@ private:
176
179
 
177
180
  namespace registry {
178
181
 
179
- // Connect to an ESI accelerator given a backend name and connection specifier.
180
- // Alternatively, instantiate the backend directly (if you're using C++).
181
- std::unique_ptr<AcceleratorConnection> connect(Context &ctxt,
182
- const std::string &backend,
183
- const std::string &connection);
184
-
185
182
  namespace internal {
186
183
 
187
184
  /// Backends can register themselves to be connected via a connection string.
@@ -51,19 +51,19 @@ public:
51
51
  ctxt = Context::withLogger<ConsoleLogger>(Logger::Level::Debug);
52
52
  else if (verbose)
53
53
  ctxt = Context::withLogger<ConsoleLogger>(Logger::Level::Info);
54
+ else
55
+ ctxt = Context::withLogger<ConsoleLogger>(Logger::Level::Warning);
54
56
  return 0;
55
57
  }
56
58
 
57
59
  /// Connect to the accelerator using the specified backend and connection.
58
- std::unique_ptr<AcceleratorConnection> connect() {
59
- return ctxt.connect(backend, connStr);
60
- }
60
+ AcceleratorConnection *connect() { return ctxt->connect(backend, connStr); }
61
61
 
62
62
  /// Get the context.
63
- Context &getContext() { return ctxt; }
63
+ Context &getContext() { return *ctxt; }
64
64
 
65
65
  protected:
66
- Context ctxt;
66
+ std::unique_ptr<Context> ctxt;
67
67
 
68
68
  std::string backend;
69
69
  std::string connStr;