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
@@ -0,0 +1,218 @@
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
+ //===----------------------------------------------------------------------===//
16
+
17
+ import Cosim_DpiPkg::*;
18
+
19
+ module Cosim_Endpoint_ToHost
20
+ #(
21
+ parameter string ENDPOINT_ID = "",
22
+ parameter string TO_HOST_TYPE_ID = "",
23
+ parameter int TO_HOST_SIZE_BITS = -1
24
+ )
25
+ (
26
+ input logic clk,
27
+ input logic rst,
28
+
29
+ input logic DataInValid,
30
+ output logic DataInReady,
31
+ input logic [TO_HOST_SIZE_BITS-1:0] DataIn
32
+ );
33
+
34
+ initial begin
35
+ int rc;
36
+ rc = cosim_init();
37
+ if (rc != 0)
38
+ $error("Cosim init failed (%d)", rc);
39
+ rc = cosim_ep_register(ENDPOINT_ID, "", 0,
40
+ TO_HOST_TYPE_ID, TO_HOST_SIZE_BYTES);
41
+ if (rc != 0)
42
+ $error("Cosim endpoint (%s) register failed: %d", ENDPOINT_ID, rc);
43
+ end
44
+
45
+ /// **********************
46
+ /// Data in management.
47
+ ///
48
+
49
+ localparam int TO_HOST_SIZE_BYTES = int'((TO_HOST_SIZE_BITS+7)/8);
50
+ // The number of bits over a byte.
51
+ localparam int TO_HOST_SIZE_BITS_DIFF = TO_HOST_SIZE_BITS % 8;
52
+ localparam int TO_HOST_SIZE_BYTES_FLOOR = int'(TO_HOST_SIZE_BITS/8);
53
+ localparam int TO_HOST_SIZE_BYTES_FLOOR_IN_BITS
54
+ = TO_HOST_SIZE_BYTES_FLOOR * 8;
55
+
56
+ assign DataInReady = 1'b1;
57
+ byte unsigned DataInBuffer[TO_HOST_SIZE_BYTES-1:0];
58
+
59
+ always@(posedge clk) begin
60
+ if (~rst) begin
61
+ if (DataInValid) begin
62
+ int rc;
63
+ rc = cosim_ep_tryput(ENDPOINT_ID, DataInBuffer, TO_HOST_SIZE_BYTES);
64
+ if (rc != 0)
65
+ $error("cosim_ep_tryput(%s, *, %d) = %d Error! (Data lost)",
66
+ ENDPOINT_ID, TO_HOST_SIZE_BYTES, rc);
67
+ end
68
+ end
69
+ end
70
+
71
+ // Assign packed input bit array to unpacked byte array.
72
+ genvar iIn;
73
+ generate
74
+ for (iIn=0; iIn<TO_HOST_SIZE_BYTES_FLOOR; iIn++)
75
+ assign DataInBuffer[iIn] = DataIn[((iIn+1)*8)-1:iIn*8];
76
+ if (TO_HOST_SIZE_BITS_DIFF != 0)
77
+ // If the type is not a multiple of 8, we've got to copy the extra bits.
78
+ assign DataInBuffer[TO_HOST_SIZE_BYTES - 1]
79
+ [TO_HOST_SIZE_BITS_DIFF - 1:0] =
80
+ DataIn[(TO_HOST_SIZE_BYTES_FLOOR_IN_BITS +
81
+ TO_HOST_SIZE_BITS_DIFF - 1) :
82
+ TO_HOST_SIZE_BYTES_FLOOR_IN_BITS];
83
+ endgenerate
84
+
85
+ endmodule
86
+
87
+ module Cosim_Endpoint_FromHost
88
+ #(
89
+ parameter string ENDPOINT_ID = "",
90
+ parameter string FROM_HOST_TYPE_ID = "",
91
+ parameter int FROM_HOST_SIZE_BITS = -1
92
+ )
93
+ (
94
+ input logic clk,
95
+ input logic rst,
96
+
97
+ output logic DataOutValid,
98
+ input logic DataOutReady,
99
+ output logic [FROM_HOST_SIZE_BITS-1:0] DataOut
100
+ );
101
+
102
+ // Handle initialization logic.
103
+ initial begin
104
+ int rc;
105
+ rc = cosim_init();
106
+ if (rc != 0)
107
+ $error("Cosim init failed (%d)", rc);
108
+ rc = cosim_ep_register(ENDPOINT_ID, FROM_HOST_TYPE_ID, FROM_HOST_SIZE_BYTES,
109
+ "", 0);
110
+ if (rc != 0)
111
+ $error("Cosim endpoint (%s) register failed: %d", ENDPOINT_ID, rc);
112
+ end
113
+
114
+ /// ***********************
115
+ /// Useful constants.
116
+
117
+ localparam int FROM_HOST_SIZE_BYTES = int'((FROM_HOST_SIZE_BITS+7)/8);
118
+ // The number of bits over a byte.
119
+ localparam int FROM_HOST_SIZE_BITS_DIFF = FROM_HOST_SIZE_BITS % 8;
120
+ localparam int FROM_HOST_SIZE_BYTES_FLOOR = int'(FROM_HOST_SIZE_BITS/8);
121
+ localparam int FROM_HOST_SIZE_BYTES_FLOOR_IN_BITS
122
+ = FROM_HOST_SIZE_BYTES_FLOOR * 8;
123
+
124
+ // Buffer to hold incoming data directly from the DPI calls.
125
+ byte unsigned DataOutBuffer[FROM_HOST_SIZE_BYTES-1:0];
126
+
127
+ // Pipeline interface signals for buffering DataOut.
128
+ // DataOut_a_valid is asserted when a complete message is available in
129
+ // DataOut_a buffer and waiting to be accepted by the skid buffer.
130
+ logic DataOut_a_valid;
131
+ // Packed representation of the byte buffer to feed the skid input.
132
+ logic [FROM_HOST_SIZE_BITS-1:0] DataOut_a;
133
+ // Ready/valid wires between this module and the skid buffer.
134
+ wire DataOut_a_ready;
135
+ wire DataOut_x_valid;
136
+ wire [FROM_HOST_SIZE_BITS-1:0] DataOut_x;
137
+
138
+ always @(posedge clk) begin
139
+ if (~rst) begin
140
+ // If the skid buffer accepted the input token this cycle, clear the
141
+ // internal valid that indicates we have buffered data.
142
+ if (DataOut_a_valid && DataOut_a_ready)
143
+ DataOut_a_valid <= 1'b0;
144
+
145
+ // Only attempt to fetch data from the host when the skid buffer can
146
+ // accept it (DataOut_a_ready).
147
+ if (!DataOut_a_valid && DataOut_a_ready) begin
148
+ int data_limit;
149
+ int rc;
150
+
151
+ data_limit = FROM_HOST_SIZE_BYTES;
152
+ rc = cosim_ep_tryget(ENDPOINT_ID, DataOutBuffer, data_limit);
153
+ if (rc < 0) begin
154
+ $error("cosim_ep_tryget(%s, *, %d -> %d) returned an error (%d)",
155
+ ENDPOINT_ID, FROM_HOST_SIZE_BYTES, data_limit, rc);
156
+ end else if (rc > 0) begin
157
+ $error("cosim_ep_tryget(%s, *, %d -> %d) had data left over! (%d)",
158
+ ENDPOINT_ID, FROM_HOST_SIZE_BYTES, data_limit, rc);
159
+ end else if (rc == 0) begin
160
+ if (data_limit == FROM_HOST_SIZE_BYTES)
161
+ DataOut_a_valid <= 1'b1;
162
+ else if (data_limit == 0)
163
+ begin end // No message.
164
+ else
165
+ $error(
166
+ "cosim_ep_tryget(%s, *, %d -> %d) did not load entire buffer!",
167
+ ENDPOINT_ID, FROM_HOST_SIZE_BYTES, data_limit);
168
+ end
169
+ end
170
+ end else begin
171
+ DataOut_a_valid <= 1'b0;
172
+ end
173
+ end
174
+
175
+ // Pack the byte array into a single vector that will be handed to the
176
+ // skid buffer as its input payload.
177
+ genvar iOut;
178
+ generate
179
+ for (iOut=0; iOut<FROM_HOST_SIZE_BYTES_FLOOR; iOut++)
180
+ assign DataOut_a[((iOut+1)*8)-1:iOut*8] = DataOutBuffer[iOut];
181
+ if (FROM_HOST_SIZE_BITS_DIFF != 0)
182
+ // If the type is not a multiple of 8, copy the extra bits.
183
+ assign DataOut_a[(FROM_HOST_SIZE_BYTES_FLOOR_IN_BITS +
184
+ FROM_HOST_SIZE_BITS_DIFF - 1) :
185
+ FROM_HOST_SIZE_BYTES_FLOOR_IN_BITS]
186
+ = DataOutBuffer[FROM_HOST_SIZE_BYTES - 1]
187
+ [FROM_HOST_SIZE_BITS_DIFF - 1 : 0];
188
+ endgenerate
189
+
190
+ /// *******************
191
+ /// Data out management.
192
+ ///
193
+ /// It has been observed that some simulators (verilator) does not handle
194
+ /// combinational driving from DPI well (resulting in non-determinism wrt
195
+ /// some of the combinational outputs being dropped/replicated). Questa does
196
+ /// not show this behavior.
197
+ /// A mitigation is to add a skid buffer to decouple the DPI interface
198
+ /// from the output interface.
199
+
200
+ // Instantiate a single-stage pipeline to buffer tokens that arrive from
201
+ // the host and present them to the module's output with proper
202
+ // ready/valid handshaking.
203
+ ESI_PipelineStage #(.WIDTH(FROM_HOST_SIZE_BITS)) out_pipe (
204
+ .clk(clk),
205
+ .rst(rst),
206
+ .a_valid(DataOut_a_valid),
207
+ .a(DataOut_a),
208
+ .a_ready(DataOut_a_ready),
209
+ .x_valid(DataOut_x_valid),
210
+ .x(DataOut_x),
211
+ .x_ready(DataOutReady)
212
+ );
213
+
214
+ // Drive the module's outward-facing signals from the pipeline output.
215
+ assign DataOutValid = DataOut_x_valid;
216
+ assign DataOut = DataOut_x;
217
+
218
+ 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_fst_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
+ VerilatedFstC *tfp = nullptr;
68
+ #endif
69
+
70
+ if (waveformFile) {
71
+ #ifdef TRACE
72
+ tfp = new VerilatedFstC();
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
+ #ifdef TRACE
99
+ if (tfp)
100
+ tfp->dump(timeStamp);
101
+ #endif
102
+ dut.clk = !dut.clk;
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
+ #ifdef TRACE
112
+ if (tfp)
113
+ tfp->dump(timeStamp);
114
+ #endif
115
+ dut.clk = !dut.clk;
116
+
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,74 @@
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
+ // Allow reading environment variables to control waveform dumping.
22
+ import "DPI-C" function string getenv(input string env_name);
23
+
24
+ module driver();
25
+
26
+ // If the SAVE_WAVE environment variable is set, dump a VCD waveform to that
27
+ // filename.
28
+ initial begin
29
+ string save_wave = getenv("SAVE_WAVE");
30
+ if (save_wave != "") begin
31
+ $display("[driver] Saving waveform to %s", save_wave);
32
+ $dumpfile(save_wave);
33
+ $dumpvars(0, driver);
34
+ end
35
+ end
36
+
37
+ logic clk = 0;
38
+ logic rst = 0;
39
+
40
+ `TOP_MODULE top (
41
+ .clk(clk),
42
+ .rst(rst)
43
+ );
44
+
45
+ always begin
46
+ // A clock period is #4.
47
+ clk = ~clk;
48
+ #2;
49
+ end
50
+
51
+ initial begin
52
+ int cycles;
53
+
54
+ $display("[driver] Starting simulation");
55
+
56
+ rst = 1;
57
+ // Hold in reset for 4 cycles.
58
+ @(posedge clk);
59
+ @(posedge clk);
60
+ @(posedge clk);
61
+ @(posedge clk);
62
+ rst = 0;
63
+
64
+ if ($value$plusargs ("cycles=%d", cycles)) begin
65
+ int i;
66
+ for (i = 0; i < cycles; i++) begin
67
+ @(posedge clk);
68
+ end
69
+ $display("[driver] Ending simulation at tick #%0d", $time);
70
+ $finish();
71
+ end
72
+ end
73
+
74
+ endmodule
@@ -0,0 +1,141 @@
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 Questa(Simulator):
13
+ """Run and compile funcs for Questasim."""
14
+
15
+ DefaultDriver = CosimCollateralDir / "driver.sv"
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
+ # An optional list of questa error codes to suppress
29
+ suppressed_questa_errors: Optional[List[int]] = None):
30
+ super().__init__(
31
+ sources=sources,
32
+ run_dir=run_dir,
33
+ debug=debug,
34
+ run_stdout_callback=run_stdout_callback,
35
+ run_stderr_callback=run_stderr_callback,
36
+ compile_stdout_callback=compile_stdout_callback,
37
+ compile_stderr_callback=compile_stderr_callback,
38
+ make_default_logs=make_default_logs,
39
+ macro_definitions=macro_definitions,
40
+ )
41
+ self.suppressed_questa_errors = suppressed_questa_errors
42
+
43
+ # Questa doesn't use stderr for error messages. Everything goes to stdout.
44
+ UsesStderr = False
45
+
46
+ def internal_compile_commands(self) -> List[str]:
47
+ cmds = [
48
+ "onerror { quit -f -code 1 }",
49
+ ]
50
+ sources = self.sources.rtl_sources
51
+ sources.append(Questa.DefaultDriver)
52
+
53
+ # Format macro definition command
54
+ if self.macro_definitions:
55
+ macro_definitions_cmd = " ".join([
56
+ f"+define+{k}={v}" if v is not None else f"+define+{k}"
57
+ for k, v in self.macro_definitions.items()
58
+ ])
59
+ else:
60
+ macro_definitions_cmd = ""
61
+
62
+ # Format error suppression command
63
+ if self.suppressed_questa_errors:
64
+ suppressed_questa_errors_cmd = " ".join(
65
+ [f"-suppress {ec}" for ec in self.suppressed_questa_errors])
66
+ else:
67
+ suppressed_questa_errors_cmd = ""
68
+
69
+ for src in sources:
70
+ cmds.append(
71
+ f"vlog -incr +acc -sv {macro_definitions_cmd} {suppressed_questa_errors_cmd} +define+TOP_MODULE={self.sources.top}"
72
+ f" +define+SIMULATION {src.as_posix()}")
73
+ cmds.append(f"vopt -incr driver -o driver_opt +acc")
74
+ return cmds
75
+
76
+ def compile_commands(self) -> List[List[str]]:
77
+ with open("compile.do", "w") as f:
78
+ for cmd in self.internal_compile_commands():
79
+ f.write(cmd)
80
+ f.write("\n")
81
+ f.write("quit\n")
82
+ return [
83
+ ["vsim", "-batch", "-do", "compile.do"],
84
+ ]
85
+
86
+ def run_command(self, gui: bool) -> List[str]:
87
+ vsim = "vsim"
88
+ # Note: vsim exit codes say nothing about the test run's pass/fail even
89
+ # if $fatal is encountered in the simulation.
90
+ if gui:
91
+ cmd = [
92
+ vsim,
93
+ "driver_opt",
94
+ ]
95
+ else:
96
+ cmd = [
97
+ vsim,
98
+ "driver_opt",
99
+ "-batch",
100
+ ]
101
+
102
+ if self.debug:
103
+ # Create waveform dump .do file
104
+ wave_file = Path("wave.do")
105
+ with wave_file.open("w") as f:
106
+ f.write("log -r /*\n")
107
+ cmd += [
108
+ "-do",
109
+ str(wave_file.resolve()),
110
+ ]
111
+ # Questa will by default log to a vsim.wlf file in the current
112
+ # directory.
113
+ print(
114
+ f"Debug mode enabled - waveform will be in {wave_file.resolve().parent / 'vsim.wlf'}"
115
+ )
116
+
117
+ cmd += [
118
+ "-do",
119
+ "run -all",
120
+ ]
121
+
122
+ for lib in self.sources.dpi_so_paths():
123
+ svLib = os.path.splitext(lib)[0]
124
+ cmd.append("-sv_lib")
125
+ cmd.append(svLib)
126
+ return cmd
127
+
128
+ def run(self,
129
+ inner_command: str,
130
+ gui: bool = False,
131
+ server_only: bool = False) -> int:
132
+ """Override the Simulator.run() to add a soft link in the run directory (to
133
+ the work directory) before running vsim the usual way."""
134
+
135
+ # Create a soft link to the work directory.
136
+ workDir = self.run_dir / "work"
137
+ if not workDir.exists():
138
+ os.symlink(Path(os.getcwd()) / "work", workDir)
139
+
140
+ # Run the simulation.
141
+ return super().run(inner_command, gui, server_only=server_only)