esiaccel 0.1.0__cp313-cp313-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 (41) hide show
  1. esiaccel/__init__.py +13 -0
  2. esiaccel/accelerator.py +95 -0
  3. esiaccel/bin/esi-cosim.py +405 -0
  4. esiaccel/bin/esiquery +0 -0
  5. esiaccel/cmake/esiaccelConfig.cmake +15 -0
  6. esiaccel/codegen.py +197 -0
  7. esiaccel/cosim/Cosim_DpiPkg.sv +85 -0
  8. esiaccel/cosim/Cosim_Endpoint.sv +189 -0
  9. esiaccel/cosim/Cosim_Manifest.sv +32 -0
  10. esiaccel/cosim/driver.cpp +131 -0
  11. esiaccel/cosim/driver.sv +60 -0
  12. esiaccel/esiCppAccel.cpython-313-x86_64-linux-gnu.so +0 -0
  13. esiaccel/include/esi/Accelerator.h +232 -0
  14. esiaccel/include/esi/CLI.h +77 -0
  15. esiaccel/include/esi/Common.h +154 -0
  16. esiaccel/include/esi/Context.h +74 -0
  17. esiaccel/include/esi/Design.h +127 -0
  18. esiaccel/include/esi/Engines.h +124 -0
  19. esiaccel/include/esi/Logging.h +231 -0
  20. esiaccel/include/esi/Manifest.h +72 -0
  21. esiaccel/include/esi/Ports.h +275 -0
  22. esiaccel/include/esi/Services.h +404 -0
  23. esiaccel/include/esi/Types.h +182 -0
  24. esiaccel/include/esi/Utils.h +102 -0
  25. esiaccel/include/esi/backends/Cosim.h +85 -0
  26. esiaccel/include/esi/backends/RpcServer.h +55 -0
  27. esiaccel/include/esi/backends/Trace.h +87 -0
  28. esiaccel/lib/libCosimBackend.so +0 -0
  29. esiaccel/lib/libESICppRuntime.so +0 -0
  30. esiaccel/lib/libEsiCosimDpiServer.so +0 -0
  31. esiaccel/lib/libMtiPli.so +0 -0
  32. esiaccel/lib/libz.so.1 +0 -0
  33. esiaccel/lib/libz.so.1.2.13 +0 -0
  34. esiaccel/types.py +512 -0
  35. esiaccel/utils.py +36 -0
  36. esiaccel-0.1.0.dist-info/METADATA +254 -0
  37. esiaccel-0.1.0.dist-info/RECORD +41 -0
  38. esiaccel-0.1.0.dist-info/WHEEL +6 -0
  39. esiaccel-0.1.0.dist-info/entry_points.txt +4 -0
  40. esiaccel-0.1.0.dist-info/licenses/LICENSE +234 -0
  41. esiaccel-0.1.0.dist-info/top_level.txt +1 -0
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
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 = AcceleratorConnection("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 = AcceleratorConnection(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,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
@@ -0,0 +1,32 @@
1
+ //===- Cosim_Manifest.sv - ESI manifest 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 needs to instantiate this ONCE with the zlib-compressed
10
+ // JSON manifest as the parameter.
11
+ //
12
+ //===----------------------------------------------------------------------===//
13
+
14
+ import Cosim_DpiPkg::*;
15
+
16
+ module Cosim_Manifest
17
+ #(
18
+ parameter int COMPRESSED_MANIFEST_SIZE = 0,
19
+ parameter int unsigned ESI_VERSION = 0
20
+ )(
21
+ input logic [COMPRESSED_MANIFEST_SIZE-1:0][7:0] compressed_manifest
22
+ );
23
+
24
+ byte unsigned compressed_manifest_bytes[COMPRESSED_MANIFEST_SIZE-1:0];
25
+ always_comb
26
+ for (int i=0; i<COMPRESSED_MANIFEST_SIZE; i++)
27
+ compressed_manifest_bytes[i] = compressed_manifest[i];
28
+
29
+ always@(compressed_manifest)
30
+ cosim_set_manifest(ESI_VERSION, compressed_manifest_bytes);
31
+
32
+ endmodule
@@ -0,0 +1,131 @@
1
+ //===- driver.cpp - ESI Verilator software driver -------------------------===//
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 fairly standard, boilerplate Verilator C++ simulation driver. Assumes the
10
+ // top level exposes just two signals: 'clk' and 'rst'.
11
+ //
12
+ //===----------------------------------------------------------------------===//
13
+
14
+ #ifndef TOP_MODULE
15
+ #define TOP_MODULE ESI_Cosim_Top
16
+ #endif // TOP_MODULE
17
+
18
+ // Macro black magic to get the header file name and class name from the
19
+ // TOP_MODULE macro. Need to disable formatting for this section, as
20
+ // clang-format messes it up by inserting spaces.
21
+
22
+ // clang-format off
23
+ #define STRINGIFY_MACRO(x) STR(x)
24
+ #define STR(x) #x
25
+ #define EXPAND(x)x
26
+ #define CONCAT3(n1, n2, n3) STRINGIFY_MACRO(EXPAND(n1)EXPAND(n2)EXPAND(n3))
27
+ #define TOKENPASTE(x, y) x ## y
28
+ #define CLASSNAME(x, y) TOKENPASTE(x, y)
29
+
30
+ #include CONCAT3(V,TOP_MODULE,.h)
31
+ // clang-format on
32
+
33
+ #include "verilated_vcd_c.h"
34
+
35
+ #include "signal.h"
36
+ #include <iostream>
37
+ #include <thread>
38
+
39
+ vluint64_t timeStamp;
40
+
41
+ // Stop the simulation gracefully on ctrl-c.
42
+ volatile bool stopSimulation = false;
43
+ void handle_sigint(int) { stopSimulation = true; }
44
+
45
+ // Called by $time in Verilog.
46
+ double sc_time_stamp() { return timeStamp; }
47
+
48
+ int main(int argc, char **argv) {
49
+ // Register graceful exit handler.
50
+ signal(SIGINT, handle_sigint);
51
+
52
+ Verilated::commandArgs(argc, argv);
53
+
54
+ // Construct the simulated module's C++ model.
55
+ auto &dut = *new CLASSNAME(V, TOP_MODULE)();
56
+ char *waveformFile = getenv("SAVE_WAVE");
57
+
58
+ char *periodStr = getenv("DEBUG_PERIOD");
59
+ unsigned debugPeriod = 0;
60
+ if (periodStr) {
61
+ debugPeriod = std::stoi(periodStr);
62
+ std::cout << "[driver] Setting debug period to " << debugPeriod
63
+ << std::endl;
64
+ }
65
+
66
+ #ifdef TRACE
67
+ VerilatedVcdC *tfp = nullptr;
68
+ #endif
69
+
70
+ if (waveformFile) {
71
+ #ifdef TRACE
72
+ tfp = new VerilatedVcdC();
73
+ Verilated::traceEverOn(true);
74
+ dut.trace(tfp, 99); // Trace 99 levels of hierarchy
75
+ tfp->open(waveformFile);
76
+ std::cout << "[driver] Writing trace to " << waveformFile << std::endl;
77
+ #else
78
+ std::cout
79
+ << "[driver] Warning: waveform file specified, but not a debug build"
80
+ << std::endl;
81
+ #endif
82
+ }
83
+
84
+ std::cout << "[driver] Starting simulation" << std::endl;
85
+
86
+ // TODO: Add max speed (cycles per second) option for small, interactive
87
+ // simulations to reduce waveform for debugging. Should this be a command line
88
+ // option or configurable over the cosim interface?
89
+
90
+ // Reset.
91
+ dut.rst = 1;
92
+ dut.clk = 0;
93
+
94
+ // TODO: Support ESI reset handshake in the future.
95
+ // Run for a few cycles with reset held.
96
+ for (timeStamp = 0; timeStamp < 8 && !Verilated::gotFinish(); timeStamp++) {
97
+ dut.eval();
98
+ dut.clk = !dut.clk;
99
+ #ifdef TRACE
100
+ if (tfp)
101
+ tfp->dump(timeStamp);
102
+ #endif
103
+ }
104
+
105
+ // Take simulation out of reset.
106
+ dut.rst = 0;
107
+
108
+ // Run for the specified number of cycles out of reset.
109
+ for (; !Verilated::gotFinish() && !stopSimulation; timeStamp++) {
110
+ dut.eval();
111
+ dut.clk = !dut.clk;
112
+
113
+ #ifdef TRACE
114
+ if (tfp)
115
+ tfp->dump(timeStamp);
116
+ #endif
117
+ if (debugPeriod)
118
+ std::this_thread::sleep_for(std::chrono::milliseconds(debugPeriod));
119
+ }
120
+
121
+ // Tell the simulator that we're going to exit. This flushes the output(s) and
122
+ // frees whatever memory may have been allocated.
123
+ dut.final();
124
+ #ifdef TRACE
125
+ if (tfp)
126
+ tfp->close();
127
+ #endif
128
+
129
+ std::cout << "[driver] Ending simulation at tick #" << timeStamp << std::endl;
130
+ return 0;
131
+ }
@@ -0,0 +1,60 @@
1
+ //===- driver.sv - ESI cosim testbench driver -----------------------------===//
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
+ // Contains the top module driver for an ESI cosimulation. It simply provides a
10
+ // clock and reset signal. In the future, the reset signal will become a reset
11
+ // handshake.
12
+ //
13
+ //===----------------------------------------------------------------------===//
14
+
15
+ `timescale 1ns / 100ps
16
+
17
+ `ifndef TOP_MODULE
18
+ `define TOP_MODULE ESI_Cosim_Top
19
+ `endif
20
+
21
+ module driver();
22
+
23
+ logic clk = 0;
24
+ logic rst = 0;
25
+
26
+ `TOP_MODULE top (
27
+ .clk(clk),
28
+ .rst(rst)
29
+ );
30
+
31
+ always begin
32
+ // A clock period is #4.
33
+ clk = ~clk;
34
+ #2;
35
+ end
36
+
37
+ initial begin
38
+ int cycles;
39
+
40
+ $display("[driver] Starting simulation");
41
+
42
+ rst = 1;
43
+ // Hold in reset for 4 cycles.
44
+ @(posedge clk);
45
+ @(posedge clk);
46
+ @(posedge clk);
47
+ @(posedge clk);
48
+ rst = 0;
49
+
50
+ if ($value$plusargs ("cycles=%d", cycles)) begin
51
+ int i;
52
+ for (i = 0; i < cycles; i++) begin
53
+ @(posedge clk);
54
+ end
55
+ $display("[driver] Ending simulation at tick #%0d", $time);
56
+ $finish();
57
+ end
58
+ end
59
+
60
+ endmodule