esiaccel 0.2.3.dev49__cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.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.

Files changed (47) hide show
  1. esiaccel/__init__.py +31 -0
  2. esiaccel/accelerator.py +134 -0
  3. esiaccel/bin/esi-cosim.py +104 -0
  4. esiaccel/bin/esiquery +0 -0
  5. esiaccel/cmake/esiaccelConfig.cmake +49 -0
  6. esiaccel/codegen.py +197 -0
  7. esiaccel/cosim/Cosim_CycleCount.sv +84 -0
  8. esiaccel/cosim/Cosim_DpiPkg.sv +85 -0
  9. esiaccel/cosim/Cosim_Endpoint.sv +218 -0
  10. esiaccel/cosim/Cosim_Manifest.sv +32 -0
  11. esiaccel/cosim/driver.cpp +131 -0
  12. esiaccel/cosim/driver.sv +74 -0
  13. esiaccel/cosim/questa.py +141 -0
  14. esiaccel/cosim/simulator.py +383 -0
  15. esiaccel/cosim/verilator.py +92 -0
  16. esiaccel/esiCppAccel.cpython-314-x86_64-linux-gnu.so +0 -0
  17. esiaccel/esiCppAccel.pyi +337 -0
  18. esiaccel/include/esi/Accelerator.h +229 -0
  19. esiaccel/include/esi/CLI.h +77 -0
  20. esiaccel/include/esi/Common.h +182 -0
  21. esiaccel/include/esi/Context.h +82 -0
  22. esiaccel/include/esi/Design.h +132 -0
  23. esiaccel/include/esi/Engines.h +124 -0
  24. esiaccel/include/esi/Logging.h +231 -0
  25. esiaccel/include/esi/Manifest.h +70 -0
  26. esiaccel/include/esi/Ports.h +482 -0
  27. esiaccel/include/esi/Services.h +467 -0
  28. esiaccel/include/esi/Types.h +334 -0
  29. esiaccel/include/esi/Utils.h +102 -0
  30. esiaccel/include/esi/Values.h +313 -0
  31. esiaccel/include/esi/backends/Cosim.h +78 -0
  32. esiaccel/include/esi/backends/RpcClient.h +97 -0
  33. esiaccel/include/esi/backends/RpcServer.h +73 -0
  34. esiaccel/include/esi/backends/Trace.h +87 -0
  35. esiaccel/lib/libCosimBackend.so +0 -0
  36. esiaccel/lib/libCosimRpc.so +0 -0
  37. esiaccel/lib/libESICppRuntime.so +0 -0
  38. esiaccel/lib/libEsiCosimDpiServer.so +0 -0
  39. esiaccel/lib/libMtiPli.so +0 -0
  40. esiaccel/types.py +565 -0
  41. esiaccel/utils.py +54 -0
  42. esiaccel-0.2.3.dev49.dist-info/METADATA +254 -0
  43. esiaccel-0.2.3.dev49.dist-info/RECORD +47 -0
  44. esiaccel-0.2.3.dev49.dist-info/WHEEL +6 -0
  45. esiaccel-0.2.3.dev49.dist-info/entry_points.txt +4 -0
  46. esiaccel-0.2.3.dev49.dist-info/licenses/LICENSE +234 -0
  47. esiaccel-0.2.3.dev49.dist-info/top_level.txt +1 -0
esiaccel/__init__.py ADDED
@@ -0,0 +1,31 @@
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
+ import sys
5
+ import os
6
+ from .accelerator import AcceleratorConnection, Context, LogLevel
7
+
8
+ from .esiCppAccel import (AppID, Type, BundleType, ChannelType, ArrayType,
9
+ StructType, BitsType, UIntType, SIntType)
10
+
11
+ __all__ = [
12
+ "AcceleratorConnection", "AppID", "Context", "LogLevel", "Type",
13
+ "BundleType", "ChannelType", "ArrayType", "StructType", "BitsType",
14
+ "UIntType", "SIntType"
15
+ ]
16
+
17
+ if sys.platform == "win32":
18
+ """Ensure that ESI libraries are in the dll path on Windows. Necessary to
19
+ call when users build against the esiaccel-provided prebuilt CMake/prebuilt
20
+ libraries, before they are loaded via. python.
21
+ """
22
+ from .utils import get_dll_dir
23
+ os.add_dll_directory(str(get_dll_dir()))
24
+
25
+
26
+ def connect(platform: str, connection_str: str) -> "AcceleratorConnection":
27
+ """Connect to an accelerator using the specified platform and connection
28
+ string."""
29
+ ctxt = Context.default()
30
+ return AcceleratorConnection(ctxt,
31
+ ctxt.cpp_ctxt.connect(platform, connection_str))
@@ -0,0 +1,134 @@
1
+ # ===-----------------------------------------------------------------------===#
2
+ # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3
+ # See https://llvm.org/LICENSE.txt for license information.
4
+ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5
+ # ===-----------------------------------------------------------------------===#
6
+ #
7
+ # The structure of the Python classes and hierarchy roughly mirrors the C++
8
+ # side, but wraps the C++ objects. The wrapper classes sometimes add convenience
9
+ # functionality and serve to return wrapped versions of the returned objects.
10
+ #
11
+ # ===-----------------------------------------------------------------------===#
12
+
13
+ from typing import Dict, List, Optional
14
+
15
+ from .types import BundlePort
16
+ from . import esiCppAccel as cpp
17
+
18
+ LogLevel = cpp.LogLevel
19
+
20
+
21
+ class Context:
22
+ """A context for ESI accelerator connections. The underlying C++ context owns
23
+ everything assocated with it including types, accelerator connections, and
24
+ the accelerator facade/interface (aka Accelerator) itself. It must not be
25
+ garbage collected while any accelerators or connections that it owns are still
26
+ in use as they will be disconnected and destroyed when the context is
27
+ destroyed."""
28
+
29
+ _default: Optional["Context"] = None
30
+
31
+ def __init__(self, log_level: cpp.LogLevel = cpp.LogLevel.Warning):
32
+ self.cpp_ctxt = cpp.Context()
33
+ self.set_stdio_logger(log_level)
34
+
35
+ @staticmethod
36
+ def default() -> "Context":
37
+ if Context._default is None:
38
+ Context._default = Context()
39
+ return Context._default
40
+
41
+ def set_stdio_logger(self, level: cpp.LogLevel):
42
+ self.cpp_ctxt.set_stdio_logger(level)
43
+
44
+ def connect(self, platform: str,
45
+ connection_str: str) -> "AcceleratorConnection":
46
+ return AcceleratorConnection(
47
+ self, self.cpp_ctxt.connect(platform, connection_str))
48
+
49
+
50
+ class AcceleratorConnection:
51
+ """A connection to an ESI accelerator."""
52
+
53
+ def __init__(self, ctxt: Context, cpp_accel: cpp.AcceleratorConnection):
54
+ if not isinstance(ctxt, Context):
55
+ raise TypeError("ctxt must be a Context")
56
+ self.ctxt = ctxt
57
+ self.cpp_accel = cpp_accel
58
+
59
+ def manifest(self) -> cpp.Manifest:
60
+ """Get and parse the accelerator manifest."""
61
+ return cpp.Manifest(self.ctxt.cpp_ctxt,
62
+ self.cpp_accel.sysinfo().json_manifest())
63
+
64
+ def sysinfo(self) -> cpp.SysInfo:
65
+ return self.cpp_accel.sysinfo()
66
+
67
+ def build_accelerator(self) -> "Accelerator":
68
+ return Accelerator(self.manifest().build_accelerator(self.cpp_accel))
69
+
70
+ def get_service_mmio(self) -> cpp.MMIO:
71
+ return self.cpp_accel.get_service_mmio()
72
+
73
+ def get_service_hostmem(self) -> cpp.HostMem:
74
+ return self.cpp_accel.get_service_hostmem()
75
+
76
+ def get_accelerator(self) -> "Accelerator":
77
+ """
78
+ Return an accelerator that may be owned by this accelerator connection.
79
+ If no accelerator is owned, will throw.
80
+ """
81
+ return Accelerator(self.cpp_accel.get_accelerator())
82
+
83
+
84
+ from .esiCppAccel import HostMemOptions
85
+
86
+
87
+ class HWModule:
88
+ """Represents either the top level or an instance of a hardware module."""
89
+
90
+ def __init__(self, parent: Optional["HWModule"], cpp_hwmodule: cpp.HWModule):
91
+ self.parent = parent
92
+ self.cpp_hwmodule = cpp_hwmodule
93
+
94
+ @property
95
+ def children(self) -> Dict[cpp.AppID, "Instance"]:
96
+ return {
97
+ name: Instance(self, inst)
98
+ for name, inst in self.cpp_hwmodule.children.items()
99
+ }
100
+
101
+ @property
102
+ def ports(self) -> Dict[cpp.AppID, BundlePort]:
103
+ return {
104
+ name: BundlePort(self, port)
105
+ for name, port in self.cpp_hwmodule.ports.items()
106
+ }
107
+
108
+ @property
109
+ def services(self) -> List[cpp.AppID]:
110
+ return self.cpp_hwmodule.services
111
+
112
+
113
+ MMIO = cpp.MMIO
114
+
115
+
116
+ class Instance(HWModule):
117
+ """Subclass of `HWModule` which represents a submodule instance. Adds an
118
+ AppID, which the top level doesn't have or need."""
119
+
120
+ def __init__(self, parent: Optional["HWModule"], cpp_instance: cpp.Instance):
121
+ super().__init__(parent, cpp_instance)
122
+ self.cpp_hwmodule: cpp.Instance = cpp_instance
123
+
124
+ @property
125
+ def id(self) -> cpp.AppID:
126
+ return self.cpp_hwmodule.id
127
+
128
+
129
+ class Accelerator(HWModule):
130
+ """Root of the accelerator design hierarchy."""
131
+
132
+ def __init__(self, cpp_accelerator: cpp.Accelerator):
133
+ super().__init__(None, cpp_accelerator)
134
+ self.cpp_hwmodule = cpp_accelerator
@@ -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))
esiaccel/bin/esiquery ADDED
Binary file
@@ -0,0 +1,49 @@
1
+ add_library(esiaccel::ESICppRuntime SHARED IMPORTED)
2
+ set_target_properties(esiaccel::ESICppRuntime PROPERTIES
3
+ INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_LIST_DIR}/../include"
4
+ )
5
+
6
+ if(WIN32)
7
+ set_target_properties(esiaccel::ESICppRuntime PROPERTIES
8
+ IMPORTED_LOCATION "${CMAKE_CURRENT_LIST_DIR}/../ESICppRuntime.dll"
9
+ IMPORTED_IMPLIB "${CMAKE_CURRENT_LIST_DIR}/../ESICppRuntime.lib"
10
+ )
11
+ else()
12
+ set_target_properties(esiaccel::ESICppRuntime PROPERTIES
13
+ IMPORTED_LOCATION "${CMAKE_CURRENT_LIST_DIR}/../lib/libESICppRuntime.so"
14
+ )
15
+ endif()
16
+
17
+ add_library(esiaccel::CosimRpc SHARED IMPORTED)
18
+ set_target_properties(esiaccel::CosimRpc PROPERTIES
19
+ INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_LIST_DIR}/../include"
20
+ INTERFACE_LINK_LIBRARIES esiaccel::ESICppRuntime
21
+ )
22
+
23
+ if(WIN32)
24
+ set_target_properties(esiaccel::CosimRpc PROPERTIES
25
+ IMPORTED_LOCATION "${CMAKE_CURRENT_LIST_DIR}/../CosimRpc.dll"
26
+ IMPORTED_IMPLIB "${CMAKE_CURRENT_LIST_DIR}/../CosimRpc.lib"
27
+ )
28
+ else()
29
+ set_target_properties(esiaccel::CosimRpc PROPERTIES
30
+ IMPORTED_LOCATION "${CMAKE_CURRENT_LIST_DIR}/../lib/libCosimRpc.so"
31
+ )
32
+ endif()
33
+
34
+ add_library(esiaccel::CosimBackend SHARED IMPORTED)
35
+ set_target_properties(esiaccel::CosimBackend PROPERTIES
36
+ INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_LIST_DIR}/../include"
37
+ INTERFACE_LINK_LIBRARIES "esiaccel::ESICppRuntime;esiaccel::CosimRpc"
38
+ )
39
+
40
+ if(WIN32)
41
+ set_target_properties(esiaccel::CosimBackend PROPERTIES
42
+ IMPORTED_LOCATION "${CMAKE_CURRENT_LIST_DIR}/../CosimBackend.dll"
43
+ IMPORTED_IMPLIB "${CMAKE_CURRENT_LIST_DIR}/../CosimBackend.lib"
44
+ )
45
+ else()
46
+ set_target_properties(esiaccel::CosimBackend PROPERTIES
47
+ IMPORTED_LOCATION "${CMAKE_CURRENT_LIST_DIR}/../lib/libCosimBackend.so"
48
+ )
49
+ endif()
esiaccel/codegen.py ADDED
@@ -0,0 +1,197 @@
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
+ # Code generation from ESI manifests to source code. C++ header support included
6
+ # with the runtime, though it is intended to be extensible for other languages.
7
+
8
+ from typing import List, TextIO, Type, Optional
9
+ from .accelerator import AcceleratorConnection, Context
10
+ from .esiCppAccel import ModuleInfo
11
+ from . import types
12
+
13
+ import argparse
14
+ from pathlib import Path
15
+ import textwrap
16
+ import sys
17
+
18
+ _thisdir = Path(__file__).absolute().resolve().parent
19
+
20
+
21
+ class Generator:
22
+ """Base class for all generators."""
23
+
24
+ language: Optional[str] = None
25
+
26
+ def __init__(self, conn: AcceleratorConnection):
27
+ self.manifest = conn.manifest()
28
+
29
+ def generate(self, output_dir: Path, system_name: str):
30
+ raise NotImplementedError("Generator.generate() must be overridden")
31
+
32
+
33
+ class CppGenerator(Generator):
34
+ """Generate C++ headers from an ESI manifest."""
35
+
36
+ language = "C++"
37
+
38
+ # Supported bit widths for lone integer types.
39
+ int_width_support = set([8, 16, 32, 64])
40
+
41
+ def get_type_str(self, type: types.ESIType) -> str:
42
+ """Get the textual code for the storage class of a type.
43
+
44
+ Examples: uint32_t, int64_t, CustomStruct."""
45
+
46
+ if isinstance(type, (types.BitsType, types.IntType)):
47
+ if type.bit_width not in self.int_width_support:
48
+ raise ValueError(f"Unsupported integer width: {type.bit_width}")
49
+ if isinstance(type, (types.BitsType, types.UIntType)):
50
+ return f"uint{type.bit_width}_t"
51
+ return f"int{type.bit_width}_t"
52
+ raise NotImplementedError(f"Type '{type}' not supported for C++ generation")
53
+
54
+ def get_consts_str(self, module_info: ModuleInfo) -> str:
55
+ """Get the C++ code for a constant in a module."""
56
+ const_strs: List[str] = [
57
+ f"static constexpr {self.get_type_str(const.type)} "
58
+ f"{name} = 0x{const.value:x};"
59
+ for name, const in module_info.constants.items()
60
+ ]
61
+ return "\n".join(const_strs)
62
+
63
+ def write_modules(self, output_dir: Path, system_name: str):
64
+ """Write the C++ header. One for each module in the manifest."""
65
+
66
+ for module_info in self.manifest.module_infos:
67
+ s = f"""
68
+ /// Generated header for {system_name} module {module_info.name}.
69
+ #pragma once
70
+ #include "types.h"
71
+
72
+ namespace {system_name} {{
73
+ class {module_info.name} {{
74
+ public:
75
+ {self.get_consts_str(module_info)}
76
+ }};
77
+ }} // namespace {system_name}
78
+ """
79
+
80
+ hdr_file = output_dir / f"{module_info.name}.h"
81
+ with open(hdr_file, "w") as hdr:
82
+ hdr.write(textwrap.dedent(s))
83
+
84
+ def write_type(self, hdr: TextIO, type: types.ESIType):
85
+ if isinstance(type, (types.BitsType, types.IntType)):
86
+ # Bit vector types use standard C++ types.
87
+ return
88
+ raise NotImplementedError(f"Type '{type}' not supported for C++ generation")
89
+
90
+ def write_types(self, output_dir: Path, system_name: str):
91
+ hdr_file = output_dir / "types.h"
92
+ with open(hdr_file, "w") as hdr:
93
+ hdr.write(
94
+ textwrap.dedent(f"""
95
+ // Generated header for {system_name} types.
96
+ #pragma once
97
+
98
+ #include <cstdint>
99
+
100
+ namespace {system_name} {{
101
+ """))
102
+
103
+ for type in self.manifest.type_table:
104
+ try:
105
+ self.write_type(hdr, type)
106
+ except NotImplementedError:
107
+ sys.stderr.write(
108
+ f"Warning: type '{type}' not supported for C++ generation\n")
109
+
110
+ hdr.write(
111
+ textwrap.dedent(f"""
112
+ }} // namespace {system_name}
113
+ """))
114
+
115
+ def generate(self, output_dir: Path, system_name: str):
116
+ self.write_types(output_dir, system_name)
117
+ self.write_modules(output_dir, system_name)
118
+
119
+
120
+ def run(generator: Type[Generator] = CppGenerator,
121
+ cmdline_args=sys.argv) -> int:
122
+ """Create and run a generator reading options from the command line."""
123
+
124
+ argparser = argparse.ArgumentParser(
125
+ description=f"Generate {generator.language} headers from an ESI manifest",
126
+ formatter_class=argparse.RawDescriptionHelpFormatter,
127
+ epilog=textwrap.dedent("""
128
+ Can read the manifest from either a file OR a running accelerator.
129
+
130
+ Usage examples:
131
+ # To read the manifest from a file:
132
+ esi-cppgen --file /path/to/manifest.json
133
+
134
+ # To read the manifest from a running accelerator:
135
+ esi-cppgen --platform cosim --connection localhost:1234
136
+ """))
137
+
138
+ argparser.add_argument("--file",
139
+ type=str,
140
+ default=None,
141
+ help="Path to the manifest file.")
142
+ argparser.add_argument(
143
+ "--platform",
144
+ type=str,
145
+ help="Name of platform for live accelerator connection.")
146
+ argparser.add_argument(
147
+ "--connection",
148
+ type=str,
149
+ help="Connection string for live accelerator connection.")
150
+ argparser.add_argument(
151
+ "--output-dir",
152
+ type=str,
153
+ default="esi",
154
+ help="Output directory for generated files. Recommend adding either `esi`"
155
+ " or the system name to the end of the path so as to avoid header name"
156
+ "conflicts. Defaults to `esi`")
157
+ argparser.add_argument(
158
+ "--system-name",
159
+ type=str,
160
+ default="esi_system",
161
+ help="Name of the ESI system. For C++, this will be the namespace.")
162
+
163
+ if (len(cmdline_args) <= 1):
164
+ argparser.print_help()
165
+ return 1
166
+ args = argparser.parse_args(cmdline_args[1:])
167
+
168
+ if args.file is not None and args.platform is not None:
169
+ print("Cannot specify both --file and --platform")
170
+ return 1
171
+
172
+ conn: AcceleratorConnection
173
+ if args.file is not None:
174
+ conn = Context.default().connect("trace", f"-:{args.file}")
175
+ elif args.platform is not None:
176
+ if args.connection is None:
177
+ print("Must specify --connection with --platform")
178
+ return 1
179
+ conn = Context.default().connect(args.platform, args.connection)
180
+ else:
181
+ print("Must specify either --file or --platform")
182
+ return 1
183
+
184
+ output_dir = Path(args.output_dir)
185
+ if output_dir.exists() and not output_dir.is_dir():
186
+ print(f"Output directory {output_dir} is not a directory")
187
+ return 1
188
+ if not output_dir.exists():
189
+ output_dir.mkdir(parents=True)
190
+
191
+ gen = generator(conn)
192
+ gen.generate(output_dir, args.system_name)
193
+ return 0
194
+
195
+
196
+ if __name__ == '__main__':
197
+ sys.exit(run())
@@ -0,0 +1,84 @@
1
+ //===- Cosim_CycleCount.sv - ESI cycle counter 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
+ // A cosimulated design should instantiate this ONCE to provide cycle count
10
+ // information to the ESI runtime. The module maintains a 64-bit cycle counter
11
+ // and uses request/response channels to provide the count to the runtime.
12
+ //
13
+ //===----------------------------------------------------------------------===//
14
+
15
+ import Cosim_DpiPkg::*;
16
+
17
+ module Cosim_CycleCount
18
+ #(
19
+ // Core clock frequency in Hz. Used by the runtime to convert cycles to time.
20
+ parameter longint unsigned CORE_CLOCK_FREQUENCY_HZ = 0
21
+ )(
22
+ input logic clk,
23
+ input logic rst
24
+ );
25
+
26
+ // 64-bit cycle counter.
27
+ longint unsigned cycle_count;
28
+
29
+ always_ff @(posedge clk) begin
30
+ if (rst)
31
+ cycle_count <= 0;
32
+ else
33
+ cycle_count <= cycle_count + 1;
34
+ end
35
+
36
+ // Request channel (From Host)
37
+ // 0-bit message used as a trigger.
38
+ wire req_valid;
39
+ wire req_ready;
40
+
41
+ Cosim_Endpoint_FromHost #(
42
+ .ENDPOINT_ID("__cosim_cycle_count.arg"),
43
+ .FROM_HOST_TYPE_ID("!esi.channel<i1>"),
44
+ .FROM_HOST_SIZE_BITS(1)
45
+ ) req_ep (
46
+ .clk(clk),
47
+ .rst(rst),
48
+ .DataOutValid(req_valid),
49
+ .DataOutReady(req_ready),
50
+ .DataOut()
51
+ );
52
+
53
+ // Response channel (To Host)
54
+ typedef struct packed {
55
+ longint unsigned cycle;
56
+ longint unsigned freq;
57
+ } RespStruct;
58
+
59
+ wire resp_ready;
60
+ wire resp_valid;
61
+ RespStruct resp_data;
62
+
63
+ assign resp_data.cycle = cycle_count;
64
+ assign resp_data.freq = CORE_CLOCK_FREQUENCY_HZ;
65
+
66
+ // Handshake logic:
67
+ // When request arrives (req_valid), we are ready to send response (resp_valid).
68
+ // We consume request only when response is accepted.
69
+ assign resp_valid = req_valid;
70
+ assign req_ready = resp_ready;
71
+
72
+ Cosim_Endpoint_ToHost #(
73
+ .ENDPOINT_ID("__cosim_cycle_count.result"),
74
+ .TO_HOST_TYPE_ID("struct{cycle:int<64>,freq:int<64>}"),
75
+ .TO_HOST_SIZE_BITS(128)
76
+ ) resp_ep (
77
+ .clk(clk),
78
+ .rst(rst),
79
+ .DataInValid(resp_valid),
80
+ .DataInReady(resp_ready),
81
+ .DataIn(resp_data)
82
+ );
83
+
84
+ endmodule
@@ -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